
// This file is part of the Herezh++ application.
//
// The finite element software Herezh++ is dedicated to the field
// of mechanics for large transformations of solid structures.
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
//
// Herezh++ is distributed under GPL 3 license ou ultérieure.
//
// Copyright (C) 1997-2022 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL  : gerardrio56@free.fr
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.

/************************************************************************
 *     DATE:        23/01/97                                            *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *     BUT:  Class template pour la lecture d'unbloc delimite par :     *
 *            mots cles.                                                *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *                                                                      *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:                                                   *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                $     *
 ************************************************************************/
#ifndef LECTBLOC_T_H
#define LECTBLOC_T_H

#include <stdlib.h>
using namespace std;  //introduces namespace std

#include <iostream>
#include <stdlib.h>
#include "Sortie.h"
#include "UtilLecture.h"
#include "LesReferences.h"
#include "string"
#include "MotCle.h"
#include <list>
#include "string.h"
#include "Tableau_T.h"
#include "Constante.h"
#include "ParaGlob.h"


template <class T>

/// @addtogroup Goupe_relatif_aux_entrees_sorties
///  @{
///


class LectBloc
{
  public :
    // CONSTRUCTEURS :
    LectBloc () {};
    // DESTRUCTEUR :
    ~LectBloc () {};
    // METHODES PUBLIQUES :
    
    // lecture d'un bloc
    // entreePrinc : stream de lecture ( sur le fichier d'entree)
    // lesRef : liste des references generale lue
    // motcle de debut de lecture
    // message : a afficher en cas d'erreur
    // tab : tableau des information a lire
    // il faut que la classe T possede les proprietees suivantes :
    // 1) constructeur par defaut, 2) NomRef() fourni une reference sur un string contenant la 
    // reference d'identification de l'instance, 3) les operators == , != 
    // et = doivent etre surcharges, 4) Lecture(UtilLecture &) une fonction qui permet de lire
    // une instance de T sur l'unite UtilLecture , 5) Affiche () une fonction qui affiche les infos
    // specifique a la classe T, 6) NomMaillage() qui ramène un pointeur sur un nom de maillage 
    // éventuelle, le pointeur peut sinon être null.
    // les derniers arguments sont  par defaut, il permet de specifier un tableau de sous mot cle
    // delimitant des sous blocs.
    // la lecture s'arretera lorsque l'on aura trouve soit un mot cle ou soit un sous mot cle
    // saut : indique si l'instance T est a lire immediatement ou s'il faut demander une
    // nouvelle ligne avant sa lecture
    
    void Lecture(UtilLecture & entreePrinc,LesReferences& lesRef,
                 string motcle,  string message,Tableau<T>& tab,
                 Tableau<string>& TsousMot =  tab_Zero_string, bool saut = true);
                 
    
  private :  
    // VARIABLES PROTEGEES :
    // CONSTRUCTEURS :
    
    // DESTRUCTEUR :
    
    // METHODES PROTEGEES :

 };
 /// @}  // end of group

template <class T>
// lecture d'un bloc
void LectBloc<T>::Lecture(UtilLecture & entreePrinc,LesReferences& lesRef,
      string motcle, string message,Tableau<T>& tab,Tableau<string>& TsousMot,
       bool saut )
  { MotCle motCle(TsousMot); // ref aux mots cle
    if (strstr(entreePrinc.tablcar,motcle.c_str())!=NULL)
      { if (ParaGlob::NiveauImpression() >= 7) 
           cout << " lecture " << motcle << flush;
        if (saut) entreePrinc.NouvelleDonnee();
        list <T> lili;
        T elem;
        while ( !motCle.SimotCle(entreePrinc.tablcar))
         { // on initialise elem à partir d'une variable nouvellement construite par défaut
           T initial;
           elem = initial;
           // lecture
           elem.Lecture(entreePrinc);
           // on regarde si cela correspond bien a une reference existante
           if (!lesRef.Existe(elem.NomRef(),elem.NomMaillage()))
             { cout << "\n erreur, la ref " << elem.NomRef() << " de(s) " << motcle << " ne correspond a aucun element"
                   << " de la liste de reference lue !! \n";
               elem.Affiche();   
               cout << " LectBloc::Lecture( etc ..."
                   << endl;
               entreePrinc.MessageBuffer(message);  
               throw (UtilLecture::ErrNouvelleDonnee(-1));
               Sortie (1);     
             };
           // on verifie que l'on n'utilise pas deux fois la meme reference
           // pour deux cibles differentes
           typename list <T>::iterator ii;
           for (ii=lili.begin() ; ii != lili.end(); ii++)
  //              if (((*ii).NomRef() == elem.NomRef()) && ((*ii) != elem))    pour adaptation linux         
             if (((*ii).NomRef() == elem.NomRef()) && (!(elem == (*ii)))
                 && ((*ii).MemeCibleMaisDataDifferents(elem)) )          
               { // on regarde pour le nom de maillage
                 bool message = true;
                 // si les deux maillages sont différents il n'y a pas d'erreur
                 if (((*ii).NomMaillage() != NULL) && (elem.NomMaillage()!=NULL))
                   if ( *((*ii).NomMaillage()) != *(elem.NomMaillage()))  message = false;
                 if ((message) && (ParaGlob::NiveauImpression() > 0))  
                  {// on écrit un message pour avertir de l'utilisation d'une référence plusieurs
                   // fois
                   cout << "\n ---- remarque ----- , un meme nom de reference est utilisee pour"
                        << " deux cibles differentes \n";
                   cout << " premiere cible : ";  (*ii).Affiche();
                   cout << " seconde cible : "; elem.Affiche() ;    
                   if (ParaGlob::NiveauImpression() >= 4)
                           cout << " LectBloc::Lecture( etc etc .." ;
                   cout << endl; 
                   };         
         /*        cout << "\n erreur , un meme nom de reference est utilisee pour"
                      << " deux cibles differentes \n";
                 cout << " premiere cible : ";  (*ii).Affiche();
                 cout << " seconde cible : "; elem.Affiche();    
                 cout << " LectBloc::Lecture( etc etc .." << endl;
                 entreePrinc.MessageBuffer(message);                     
                 throw (UtilLecture::ErrNouvelleDonnee(-1));
                 Sortie (1);     */     
               };
           // stockage
           lili.push_back(elem);
           entreePrinc.NouvelleDonnee();
         }
        // enregistrement des infos 
        int ancien = tab.Taille();
        tab.Change_taille(((int)lili.size())+ancien);
        typename list <T>::iterator i,ifin=lili.end();
        int j;
        for (i=lili.begin(),j=1 ; i != ifin; i++,j++)
           tab(j+ancien) = *i;              
      };
  }
   

   
#endif  
