// FICHIER : ReferenceNE.cp
// CLASSE : ReferenceNE


#include "ReferenceNE.h"
#include "PtTabRel.h"

#ifndef  REFERENCENE_H_deja_inclus

#ifndef MISE_AU_POINT
  inline 
#endif
// Constructeur par defaut (appel au constructeur par defaut de Tableau<T>)
ReferenceNE::ReferenceNE (string nom):
 Reference(nom),tab_num() 
    { };
    
#ifndef MISE_AU_POINT
  inline 
#endif
// Constructeur fonction  du nb de maillage et du type de ref		
ReferenceNE::ReferenceNE (int nb , int ind) :
  Reference(nb,ind),tab_num() 
   { };
   
#ifndef MISE_AU_POINT
  inline 
#endif
// Constructeur utile si le tableau des numeros
// de la reference est connu, le nb de maillage, le type de ref
ReferenceNE::ReferenceNE (const Tableau<int>& tab,int nb, int ind, string nom):
  Reference(nom,nb,ind),tab_num(tab)
       { };

#ifndef MISE_AU_POINT
  inline 
#endif
// Constructeur utile si une liste des numeros
// de la reference est connu, le nb de maillage, le type de ref
ReferenceNE::ReferenceNE (const list <int>& list_entiers,int nb, int ind, string nom):
  Reference(nom,nb,ind),tab_num(list_entiers.size())
	{ int tail = tab_num.Taille();
	  list <int>::const_iterator it=list_entiers.begin();
	  for (int i=1;i<= tail;i++,it++)
	    tab_num(i)=(*it);
	};

#ifndef MISE_AU_POINT
  inline 
#endif
// Constructeur utile si le nom de la reference est connu 
ReferenceNE::ReferenceNE (string nom,int nb , int ind) :
  Reference(nom,nb,ind),tab_num()
       { };


#ifndef MISE_AU_POINT
  inline 
#endif
// Constructeur de copie 
ReferenceNE::ReferenceNE (const ReferenceNE& ref):
    Reference (ref),tab_num(ref.tab_num)
       { };
	
// Destructeur 
#ifndef MISE_AU_POINT
  inline 
#endif
ReferenceNE::~ReferenceNE ()
      { };

//================== METHODES : ================================
				
#ifndef MISE_AU_POINT
  inline 
#endif
Reference& ReferenceNE::operator= (const Reference& ref)
   {  *this = this->Reference::operator=(ref); // pour la partie de la classe mère
      #ifdef MISE_AU_POINT
        // vérification du type de ref
        if ((ref.Indic() != 2) && (ref.Indic() != 1))
          {if (ParaGlob::Francais()) 
			   {cout << " \n erreur dans l'affectation de reference : ReferenceNE::operator= (const Reference& ref)"
               << "\n  la reference ref n'est ni celle de noeud ni celle d'elements ";
					}
			  else  
				{cout << " \n error in the operator of reference : ReferenceNE::operator= (const Reference& ref)"
                  << "\n  the reference ref is not a reference of a node or of an element   "
                  << " or a gauss point  ";
				 };
			 };
		#endif  
      tab_num = ((ReferenceNE&) ref).tab_num;	
	  return (*this);
    };
		
		
// Affiche les donnees liees a la reference
#ifndef MISE_AU_POINT
  inline 
#endif
void ReferenceNE::Affiche () const 
		{ // affichage du type de référence
		  if (indic == 1) 
		     { if (ParaGlob::Francais()) {cout << "\n reference de noeud ";}
			    else {cout << "\n reference of node ";};}
		  else if (indic == 2)
		     { if (ParaGlob::Francais()) {cout << "\n reference d'element ";}
			    else {cout << "\n reference of element ";};}
		  else   
		     { if (ParaGlob::Francais()) {cout << "\n reference de type non défini ";}
			    else {cout << "\n reference not defined ";};}
		   // affichage pour la partie de la classe mère
		   this->Reference::Affiche();
		   // partie spécifique
			if (ParaGlob::Francais()) {cout << "Taille du tableaux : " ;}
			else {cout << "size of the tab : " ;};
			cout << tab_num.Taille() << " .\n";
			if (ParaGlob::Francais()) {cout << "Composante(s)";}
			else {cout << "Component(s)";};
         cout << " :\n\t[  ";
			for (int i=1;i<=tab_num.Taille();i++)
				cout << tab_num(i) << "  ";
			cout << "]\n\n";
		};
			
// lecture d'une liste de references de noeuds ou d'éléments
#ifndef MISE_AU_POINT
  inline 
#endif
bool ReferenceNE::LectureReference(UtilLecture & entreePrinc)
 {   *(entreePrinc.entree) >> nom_ref; // lecture d'une reference
	 // si l'on est à la fin de la ligne on passe à la ligne suivante
	 //cout << "\n rdstate " << entreePrinc.entree->rdstate() << endl;
     if ((entreePrinc.entree->eof() != 0) && (!(entreePrinc.entree->fail())))
          {   entreePrinc.NouvelleDonnee(); }
     // on utilise une liste pour la lecture, ce qui permet de lire une nombre quelconque 
     // de numéros attachés à une référence
     list <Reels1> inter; // on utilise des réels car c'est déjà défini par ailleurs
     // mais cela n'a aucune importance sur le traitement
     int il;
     
     if ((entreePrinc.entree->rdstate() != 0) 
          && (!motCle.SimotCle(entreePrinc.tablcar)))
         // si le buffer ne contiend pas de mot cle et qu'il y a un  
         //  pb de lecture ( donc pas de def de reference)
        
       { if (ParaGlob::Francais()) 
				 {cout << " \n Erreur de lecture de reference \n contenu du buffer = ";}
			else {cout << " \n Error of reference reading \n  buffer = ";};
         cout << entreePrinc.tablcar << endl;
         if (ParaGlob::Francais())
			 { entreePrinc.MessageBuffer("lecture d une  reference de noeud ou d'element");}                                  
			else  
			 {entreePrinc.MessageBuffer
             ("reading of a reference of node or element "); };                                                     
         throw (UtilLecture::ErrNouvelleDonnee(-1));
         Sortie (1);
       } 
     else if (motCle.SimotCle(entreePrinc.tablcar))
       { // fin de la lecture de reference
         // remise correcte du flot
         entreePrinc.FlotDebutDonnee();
         return false;    
       }  
     else 
     {
          // cas ou on a bien lu un nom de reference
        { 
          il = 0; // nb de nb d'entier lu
          bool fin = false;
          // les deux cas qui font sortir de la boucle sont l'apparition
          // d'un mot cle ou une erreur en lecture dans entier
          // apres une bonne lecture sur la meme ligne
          bool aumoinsune = true;
          bool prem = true; // ne sert que pour le cas d'une reference sans numero
          while ( (!fin) & aumoinsune)
           {aumoinsune = false;
            // def du maillon à lire dans la liste
            Reels1 as1;
 //           while (!entreePrinc.entree->rdstate()) // lecture tant qu'il n'y a pas d'erreur
             while ((entreePrinc.entree->rdstate()== 0)&& // lecture tant qu'il n'y a pas d'erreur
                        (!(entreePrinc.entree->eof())))
             { *(entreePrinc.entree) >> as1.donnees; // lecture d'un entier mis dans un réel      
             // pour la verif
             // pour mémoire ici on a 
           /*       enum io_state
                    {  badbit   = 1<<0, // -> 1 dans rdstate()
                       eofbit   = 1<<1, // -> 2 
                       failbit  = 1<<2, // -> 4 
                       goodbit  = 0     // -> O 
                     };*/
   //           if ((entreePrinc.entree->rdstate() == 0)||
   ///               (entreePrinc.entree->rdstate() == 2))
   //               (entreePrinc.entree->eof()))
   //          cout << "\n entreePrinc.entree->eof()" << entreePrinc.entree->eof();
   //            cout << "\n entreePrinc.entree->bad()" << entreePrinc.entree->bad();
   //            cout << "\n entreePrinc.entree->fail()" << entreePrinc.entree->fail() << endl;
             #ifdef ENLINUX
               if (entreePrinc.entree->rdstate() == 0)
             #else
         /*     #ifdef SYSTEM_MAC_OS_X_unix
               if (entreePrinc.entree->rdstate() == 0)
              #else*/
               if (((entreePrinc.entree->rdstate() == 0)||
                  (entreePrinc.entree->eof()))&&(!(entreePrinc.entree->bad()))
                  &&(!(entreePrinc.entree->fail())))
        //     #endif     
             #endif     
                 {il++;
                  aumoinsune = true;
                  prem = false;
                  inter.push_back(as1); 
                  }
              }
             
            if ((aumoinsune) || prem )                      
             {entreePrinc.NouvelleDonnee();  // lecture d'une nouvelle ligne
              if (motCle.SimotCle(entreePrinc.tablcar)) 
                // c'est un mot cle
                fin = true;
              }
            else
              // remise correcte du flot pour la lecture
              //d'une prochaine reference
              entreePrinc.FlotDebutDonnee();
            }
          if (il == 0 )
            { if (ParaGlob::Francais()) {cout << "\n WARNING : aucun numero attache a la reference = ";}
				  else                      {cout << "\n WARNING : no number linked to the reference = ";};
              cout << nom_ref << endl;
             }
          // transfert dans le tableau tab           
          tab_num.Change_taille(il);
          listdouble1Iter b; int a;
          for (b=inter.begin(),a=1 ;b != inter.end();b++,a++)
            tab_num(a) = (int) (b->donnees); // transformation en entier
          return true;
         }
      }
    return false;      
    };

// supprime les doublons internes éventuels dans la référence
#ifndef MISE_AU_POINT
  inline 
#endif
void ReferenceNE::Supprime_doublons_internes()
{ //Tableau<int> tab_num; 
  int taille = tab_num.Taille();
  list <int> agarder; // contiendra les seules numéros à sauvegarder
  for (int i=1;i<=taille;i++)
   { bool bon=true;
     for (int j=i+1;j<=taille;j++)
       if (tab_num(i)==tab_num(j))
          {bon=false;
           if (ParaGlob::NiveauImpression() > 3)
            { cout << "\n *** attention suppression doublon: ref "<<nom_ref
                   << " maillage:"<<nbmaille<<" element " << tab_num(i)<<endl;
            };
           break;
           } // cas d'un doublon
     if (bon)
       agarder.push_back(i);
   };
  int new_taille = agarder.size();
  // on modifie la liste initiale si la nouvelle taille est différente
  if (new_taille != taille)
    {list <int>::iterator ili,ilifin = agarder.end();
     int position=1;
     for (ili=agarder.begin();ili!=ilifin;ili++,position++)
        {tab_num(position) = tab_num(*ili); //position est toujours < *ili donc on écrase a partir du bas
          // et tab_num(*ili) est toujours valide
        };
     // on supprime les données de new_taille à taille
     tab_num.Change_taille(new_taille);
    };
};
    
// affichage et definition interactive des commandes 
// nbMaxi: nombre maxi de noeud ou 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
#ifndef MISE_AU_POINT
  inline 
#endif
void ReferenceNE::Info_commande_Ref(int nbMaxi,UtilLecture * entreePrinc,int cas)
 { ofstream & sort = *(entreePrinc->Commande_pointInfo()); // pour simplifier
   if (cas == 1)
	 {  if (ParaGlob::Francais()) 
			      {sort << "\n #    -- exemple de reference de noeud ";}
			  else {sort << "\n #    -- exemple of a reference of node ";};
       sort << "\n N_tout  " ;
       int compteur_ligne=0;
       for (int n1=1;n1<= nbMaxi;n1++,compteur_ligne++)
        { if (compteur_ligne > 10) 
           { compteur_ligne = 0; sort << "\n";}
          sort << setw (6) << n1 <<" ";
         }
       sort << "\n \n";
      }
   else       
     { if (indic ==1) // cas d'une ref de noeud
	      {  if (ParaGlob::Francais()) 
			      {sort << "\n #    -- exemple de reference de noeud ";}
			   else {sort << "\n #    -- exemple of a reference of node ";};
            cout << "\n N_deb   1  ";
          }
       else // cas d'une ref d'élément    
	      {  if (ParaGlob::Francais()) 
			      {sort << "\n #    -- exemple de reference d'elements ";}
			  else {sort << "\n #    -- exemple of a reference of elements ";};
           cout  << "\n E_tout_les_elements  ";
           int compteur_ligne=0;
           for (int n1=1;n1<= nbMaxi;n1++,compteur_ligne++)
            { if (compteur_ligne > 10) 
               { compteur_ligne = 0; sort << "\n";}
              sort << setw (6) << n1 <<" ";
             }
           sort << "\n \n";
         }
      }        
  };           	                 

//----- 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)
#ifndef MISE_AU_POINT
  inline 
#endif
void ReferenceNE::Lecture_base_info(ifstream& ent,const int cas)
 { // ici a priori il n'y a pas de de données supposées variables
   if (cas == 1)
     {
      // appelle de la méthode de la classe mère
        Lect_int_base_info(ent);    
      // lecture du tableau d'entier
        ent >> tab_num ;
       };
  };     
        // cas donne le niveau de sauvegarde
        // = 1 : on sauvegarde tout
        // = 2 : on sauvegarde uniquement les données variables (supposées comme telles)
#ifndef MISE_AU_POINT
  inline 
#endif
void ReferenceNE::Ecriture_base_info(ofstream& sort,const int cas)
 { // ici a priori il n'y a pas de de données supposées variables
   if (cas == 1)
     {
      // appelle de la méthode de la classe mère
        Ecrit_int_base_info(sort);    
      // écriture du tableau d'entier
      sort << tab_num;
     };
  };     
        
#ifndef MISE_AU_POINT
  inline 
#endif
// Affiche les donnees des références dans le flux passé en paramètre
void ReferenceNE::Affiche_dans_lis(ofstream&  sort) const  
  { int taille_tab= tab_num.Taille();
    // dans le cas où il n'y a pas de numéro associé à la référence on ne l'écrit pas
    if (taille_tab > 0 )
      { sort << "\n" << setw (6) << nom_ref << " ";
        int nb_par_ligne=20;
        for (int i=1,nb_p_l=1;i<=taille_tab;i++,nb_p_l++)
         { if(nb_p_l > nb_par_ligne) 
             { nb_p_l=1; sort << "\n";}
           sort << tab_num(i) << " "; 
         }
        sort << "\n";       
      }
//  #ifdef MISE_AU_POINT
    else if (ParaGlob::NiveauImpression() > 1)
     { sort <<endl;
       cout << "\n attention: ref "<<nom_ref <<" sans numero associe, on ne la sauvegarde pas ";
     }
//  #endif
  };



#endif
