/************************************************************************
 *         UNIVERSITE DE BRETAGNE SUD   --- I.U.P/I.U.T. DE LORIENT     *
 ************************************************************************
 *           LABORATOIRE DE GENIE MECANIQUE ET MATERIAUX                *
 *                        Tel 97.80.80.60                               *
 *          Centre de Genie Industriel  56520 GUIDEL-PLAGES             *
 ************************************************************************
 *     DATE:        23/01/97                                            *
 *                                                                $     *
 *     AUTEUR:      G RIO                                               *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *     BUT:     Gestion des listes de references.                       *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *                                                                      *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:                                                   *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                $     *
 ************************************************************************/
#ifndef LESREFERENCES_H
#define LESREFERENCES_H

#include "Reference.h"
#include <list>
#include <map>
#include "UtilLecture.h"
#include "MotCle.h"

//-------- une méthode permettant d'utiliser des tableaux de map de références -----
   // surcharge de l'operator d'ecriture
   ostream & operator << (ostream & sort, const map < string, Reference*, std::less <string> > & );

//----------- fin de la méthode permettant d'utiliser des tableaux de map de références -----

class LesReferences
{
  public :
    // CONSTRUCTEURS :
    LesReferences ();  // par defaut
    // DESTRUCTEUR :
    ~LesReferences ();
    // METHODES PUBLIQUES :
    
    // def du numero de maillage courant, utilise avant la lecture
    void NbMaille(int nb);
    // def du type de reference a lire, utilise avant la lecture
    // type peut-être : noeud,element,surface,arete
    void Indic(string type);
    
    // lecture des references
    void Lecture(UtilLecture & entreePrinc);
    
    // ajout d'une référence déjà construite par ailleurs
    void Ajout_reference(Reference * refi); 
    
    // suppression d'une référence 
    void SupprimeReference(const string & st1,int num_mail);
    // suppression de tous les référence d'un maillage donné
    // si avec_diminution_num_maillage = true: 
    // tous les numéros de maillage, > num_mail,  associé aux maillages qui restent
    // sont diminués de un, pour tenir compte de la disparition du maillage et donc
    // d'une nouvelle numérotation des maillages
    // si avec_diminution_num_maillage = false, le conteneur des ref de maillage num_mail
    // est vidé, mais il continu à exister: on considère qu'il y a toujours un maillage num_mail potentiel
    void Supprime_tour_lesRef_un_maillage(int num_mail, bool avec_diminution_num_maillage);
    
    // affichage des informations contenu dans les references
    // par défaut affiche toutes les infos
    // si niveau = 1 : affiche que les noms des ref
    void Affiche(int niveau=0) const ;
 
    // affichage des informations contenu dans les references d'un certain type
    // défini par indic :
    // indic =  1 -> noeud, =2 -> element
    // =3 -> surface associée à un élément , =4 -> arete associée à un élément
    // =5 -> noeud associée à un élément
    // =6 -> point d'intégration associée à un élément
    // =7 -> de points d'intégrations relatifs à des surfaces d'éléments
    // =8 -> de points d'intégrations relatifs à des arete d'éléments
    // =0 -> rien_actuellement
    // par défaut affiche toutes les infos
    // si niveau = 1 : affiche que les noms des ref
    void Affiche(int indic, int niveau) const ;
		
	   // Affiche les donnees des références pour le maillage imail dans un fichier
	   // dont le nom est construit à partir du nom du maillage au format   ".lis"
	   void Affiche_dans_lis(const string& nom_maillage,int imail);
    
    // affichage et definition interactive des commandes 
    // nbMaxiNoeud: nombre maxi de noeud pour les exemples
    // nbMaxiElem : nombre maxi d'éléments pour les exemples
    // cas : =1 premier passage, il s'agit de références de noeuds uniquement
    // cas : =2 second passage, il s'agit de l'ensemble des possibilités de références
    void Info_commande_lesRef(int nbMaxiNoeud,int nbMaxiElem,UtilLecture * entreePrinc,int cas);
    
    //--- utilisation d'une boucle pour balayer l'ensemble des références existantes:
    // ***** très important: ce balaiyage ne fonctionne que si on ne modifie pas le stockage
    // ***** par exemple en supprimant une référence existante ou en ajoutant une nouvelle référence
    // ***** ou en lisant des références (donc ajout !!)
    // ***** par contre on peut changer le contenu des références existantes
    // initialise le questionnement de la récupération de référence et
    // retourne la première référence si elle existe sinon un pointeur nul
    const Reference* Init_et_Premiere();
    // retourne la référence suivante ou, s'il n'y en n'a plus, retourne
    // un pointeur nul
    const Reference* Reference_suivante();   
    //--- fin méthode pour faire une boucle pour balayer l'ensemble des références existantes:
    
    // test si la reference existe reellement
    // retourne false si n'existe pas , true sinon
    bool Existe(const string & st1,int num_mail) const ;
    bool Existe(const string & st1,const string* nom_mail) const; 
    // retourne la reference correspondant a une cle
    const Reference& Trouve(const string & st1,int num_mail) const ;
    const Reference& Trouve(const string & st1,const string* nom_mail) const ;
    // mise à jour de la map qui fait la liaison nom de maillage <=> numéro de maillage
    void MiseAJourMap( const map < string, int , std::less <string> >& listNomMail)
          { listeNomMail = & listNomMail;};  
            
    // mise à jour des références de noeud, dans le cas où les numéros de noeuds ont changés
//1) cas où l'on supprime éventuellement des noeuds de la référence,	qui ne sont plus référencé  
    // nv_tab est tel que : nv_tab(i) est le nouveau numéro qui avait auparavant le numéro "i"
    // non_referencer(i) : = true signifie qu'il ne faut plus tenir compte de ce noeud
    //                     = false indique qu'il continue d'être actif
    void Mise_a_jour_ref_noeud(Tableau <int >& nv_tab,int num_mail,Tableau <bool>& non_referencer);
//2) cas où on considère tous les noeuds 
    // nv_tab est tel que : nv_tab(i) est le nouveau numéro qui avait auparavant le numéro "i"
    void Mise_a_jour_ref_noeud(Tableau <int >& nv_tab,int num_mail);

    // mise à jour des références d'élément, dans le cas où les numéros d'élément ont changés
//1) cas où l'on supprime éventuellement des éléments de la référence,	qui ne sont plus référencé  
    // nv_tab est tel que : nv_tab(i) est le nouveau numéro qui avait auparavant le numéro "i"
    // non_referencer(i) : = true signifie qu'il ne faut plus tenir compte de cet élément
    //                     = false indique qu'il continue d'être actif
    void Mise_a_jour_ref_element(Tableau <int >& nv_tab,int num_mail,Tableau <bool>& non_referencer);
 
    // mise à jour du numéro de maillage d'une référence
    void Mise_a_jour_num_maillage_ref(const string nom_ref, int old_num_maill, int new_num_maill)
       { Trouve_interne(nom_ref,old_num_maill).Change_Nbmaille(new_num_maill);};
    
	//----- lecture écriture dans base info -----
	// cas donne le niveau de la récupération
    // = 1 : on récupère tout
    // = 2 : on récupère uniquement les données variables (supposées comme telles)
	void Lecture_base_info(ifstream& ent,const int cas);
    // cas donne le niveau de sauvegarde
    // = 1 : on sauvegarde tout
    // = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
	void Ecriture_base_info(ofstream& sort,const int cas);

  protected :
    // variable transitoires utilise pendant la lecture
    int nbMaille; // nb courant de maillage
    int indic ; // type courant de reference : = 1 -> noeud, =2 -> element
    // =3 -> surface associée à un élément , =4 -> arete associée à un élément
    // =5 -> noeud associée à un élément
    // =6 -> point d'intégration associée à un élément
    // =7 -> de points d'intégrations relatifs à des surfaces d'éléments
    // =8 -> de points d'intégrations relatifs à des arrete d'éléments
    // =0 -> rien_actuellement
    Reference * ref; // une variable de travail
      
    // VARIABLES PROTEGEES :
//    list <Reference*> listeDeRef; // liste des references
    
    // on utilise une map pour récupérer plus rapidemment une référence à partir d'un nom
    // t_mapDeRef (i) est la map relative au maillage i
    Tableau < map < string, Reference*, std::less <string> > > t_mapDeRef;
    
    
    
    // liste des noms de maillages associée à un numéro sous forme d'un arbre pour faciliter la recherche
    const map < string,  int , std::less <string> >* listeNomMail;
    // a utiliser avec Existe et Trouve, mais pas avant la lecture, seulement après
    
    static MotCle motCle; // liste des mots clés
    
    //list <Reference*>::const_iterator iref; 
    // deux variables intermédiaires pour les méthodes Init_et_Premiere et Reference_suivante
    map < string, Reference*, std::less <string> >::const_iterator iref; 
    int num_mail_presuivant;
                             
    
    // METHODES PROTEGEES :
    // lecture d'une  reference
    bool LectureReference(UtilLecture & entreePrinc);
    // retourne la reference correspondant a une cle, en non constant
    Reference& Trouve_interne(const string & st1,int num_mail) const ;
    Reference& Trouve_interne(const string & st1,const string* nom_mail) const ;
 

 };
 
#endif  
