// 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-2021 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/>.

#include "TypeQuelconque_enum_etendu.h"


//======================== tableau tab_Daa ===============================
// on définie le  tableau des TypeQuelconque_enum_etendu qui sont validées
// en variables globales
// 1) def du tableau static
Tableau < TypeQuelconque_enum_etendu > TypeQuelconque_enum_etendu::tab_Daa(0);
int TypeQuelconque_enum_etendu::taillTab = 0;
// 2) on se sert d'un contructeur d'une class static
// pour remplir le tableau 
Initialisation_tab_Daa::Initialisation_tab_Daa()
  { Tableau < TypeQuelconque_enum_etendu >& tab_Daa = TypeQuelconque_enum_etendu::tab_Daa; // pour faciliter
    tab_Daa.Change_taille(0); TypeQuelconque_enum_etendu::taillTab = tab_Daa.Taille();
//    tab_Dee(67).nom = "logarithmique_totale11" ;tab_Dee(67).enu = EPS11;tab_Dee(67).posi_nom = nbenumddl + 67;
//    tab_Dee(68).nom = "logarithmique_totale22" ;tab_Dee(68).enu = EPS22;tab_Dee(68).posi_nom = nbenumddl + 68;
//    tab_Dee(69).nom = "logarithmique_totale33" ;tab_Dee(69).enu = EPS33;tab_Dee(69).posi_nom = nbenumddl + 69;
//    tab_Dee(70).nom = "logarithmique_totale12" ;tab_Dee(70).enu = EPS12;tab_Dee(70).posi_nom = nbenumddl + 70;
//    tab_Dee(71).nom = "logarithmique_totale13" ;tab_Dee(71).enu = EPS13;tab_Dee(71).posi_nom = nbenumddl + 71;
//    tab_Dee(72).nom = "logarithmique_totale23" ;tab_Dee(72).enu = EPS23;tab_Dee(72).posi_nom = nbenumddl + 72;
//
//    tab_Dee(73).nom = "energie_elastique" ;    tab_Dee(73).enu = EPS11; tab_Dee(73).posi_nom = nbenumddl + 73;
//    tab_Dee(74).nom = "dissipation_plastique"  ;tab_Dee(74).enu = EPS11;tab_Dee(74).posi_nom = nbenumddl + 74;
//    tab_Dee(75).nom = "dissipation_visqueuse"  ;tab_Dee(75).enu = EPS11;tab_Dee(75).posi_nom = nbenumddl + 75;
   
   }; 
// 3) initialisation réelle du tableau
Initialisation_tab_Daa TypeQuelconque_enum_etendu::init_tab_Daa;

//======================== fin tableau tab_Daa ===============================

TypeQuelconque_enum_etendu::TypeQuelconque_enum_etendu(EnumTypeQuelconque en , string no ) :
         nom(no), enu(en)  
   {// vérification dans grandeurs
    if (nom != "-")
     { bool verif = false; int posi;
       // cas 1: le nom est connu et différent d'un nom énumr
       for (int i=1;i<= taillTab;i++) 
        if (tab_Daa(i).nom == nom)
          { verif = true;posi = i; break;}
       if (verif)
         { posi_nom = ClassPourEnumTypeQuelconque::NombreEnumTypeQuelconque() + posi;
           type_grandeur = tab_Daa(posi_nom).type_grandeur;
         }
       else   
        {// cas 2: le nom est égal  un type énumr
         if (Existe_typeQuelconque(no))
          { nom ="-"; enu = Id_nomTypeQuelconque(no); posi_nom = enu;
            type_grandeur = Type_de_grandeur_associee(enu);
          }
         else   
          { cout << "\n erreur de construction d un  TypeQuelconque_enum_etendu !!"
                 << " le nom " << nom << " n'est pas connu ";
            cout << "\n TypeQuelconque_enum_etendu(EnumTypeQuelconque en = RIEN_TYPEQUELCONQUE, string no = )";
            Sortie(1);
           }
         }  
      }
    else
      {posi_nom = enu;
       type_grandeur = Type_de_grandeur_associee(enu);
      };

    }; 
    
// constructeur fonction d'un string
TypeQuelconque_enum_etendu::TypeQuelconque_enum_etendu( string no ) :
   nom(no)
   {// vérification dans grandeurs
    if (nom != "-")
     { bool verif = false; int posi;
       // cas 1: le nom est connu et différent d'un nom énumr
       for (int i=1;i<= taillTab;i++) 
        if (tab_Daa(i).nom == nom)
          { verif = true;posi = i; break;}
       if (verif)
          {posi_nom = ClassPourEnumTypeQuelconque::NombreEnumTypeQuelconque()
                       + posi;enu=tab_Daa(posi).enu;
           type_grandeur = tab_Daa(posi_nom).type_grandeur;
         }
       else
        {// cas 2: le nom est égal  un type énumr
         if (Existe_typeQuelconque(no))
          { nom ="-"; enu = Id_nomTypeQuelconque(no); posi_nom = enu;
            type_grandeur = Type_de_grandeur_associee(enu);
          }
         else   
          { cout << "\n erreur de construction d un  TypeQuelconque_enum_etendu !!"
                 << " le nom " << nom << " n'est pas connu ";
            cout << "\n TypeQuelconque_enum_etendu(EnumTypeQuelconque en = RIEN_TYPEQUELCONQUE, string no = )";
            Sortie(1);
           }
         }  
      }
    else
      { posi_nom = ClassPourEnumTypeQuelconque::NombreEnumTypeQuelconque();
        enu = RIEN_TYPEQUELCONQUE;
        type_grandeur = Type_de_grandeur_associee(enu);
       }
    }; 
    
// constructeur fonction d'un tableau de caractre
TypeQuelconque_enum_etendu::TypeQuelconque_enum_etendu( char* no ) :
   nom()
   {// vérif que le pointeur n'est pas nul
    if (no == NULL)
     { cout << "\n *** erreur de construction d'un  TypeQuelconque_enum_etendu !!"
            << " le pointeur no est nul !! ";
       cout << "\n TypeQuelconque_enum_etendu(char* no  )";
       Sortie(1);
     }
    else
     {string inter(no);
      nom = inter;
     };
   
    // vérification dans grandeurs
    if (nom != "-")
     { bool verif = false; int posi;
       // cas 1: le nom est connu et différent d'un nom énumr
       for (int i=1;i<= taillTab;i++) 
        if (tab_Daa(i).nom == nom)
          { verif = true;posi = i; break;}
       if (verif)
          {posi_nom = ClassPourEnumTypeQuelconque::NombreEnumTypeQuelconque()
                      + posi;enu=tab_Daa(posi).enu;
           type_grandeur = tab_Daa(posi_nom).type_grandeur;
          }
       else   
        {// cas 2: le nom est égal  un type énumr
         string nom(no); // on construit un string intermédiaire
         if (Existe_typeQuelconque(nom))
          { nom ="-"; enu = Id_nomTypeQuelconque(no); posi_nom = enu;
            type_grandeur = Type_de_grandeur_associee(enu);
          }
         else   
          { cout << "\n erreur de construction d un  TypeQuelconque_enum_etendu !!"
                 << " le nom " << nom << " n'est pas connu ";
            cout << "\n TypeQuelconque_enum_etendu(char* no )";
            Sortie(1);
           }
         }  
      }
    else
      { posi_nom = ClassPourEnumTypeQuelconque::NombreEnumTypeQuelconque();
        enu = RIEN_TYPEQUELCONQUE;
        type_grandeur = Type_de_grandeur_associee(enu);
       }
    };
     
// ajout d'un nouveau typeQuelconque étendu
// s'il existait avant, il n'y a pas d'ajout
// ramène un exemplaire de la création
TypeQuelconque_enum_etendu TypeQuelconque_enum_etendu::Ajout_un_TypeQuelconque_enum_etendu
             (EnumTypeQuelconque enu, const string no,EnumTypeGrandeur type_grandeur)
 { Tableau < TypeQuelconque_enum_etendu >& tab_Daa = TypeQuelconque_enum_etendu::tab_Daa; // pour faciliter
   int taille_initiale = tab_Daa.Taille();
   TypeQuelconque_enum_etendu retour; // init
   // on regarde si la grandeur existe déjà
   // 1) sur le tableau tab_Daa
   bool existe_deja = false;
   for (int i=1;i<= taille_initiale;i++)
    {if (tab_Daa(i).nom == no)
      {existe_deja = true; retour=tab_Daa(i);break;}
    };
   // 2) sur les types quelconques existants
   if (Existe_typeQuelconque(no))
    {EnumTypeQuelconque id = Id_nomTypeQuelconque(no);
     retour = TypeQuelconque_enum_etendu(id,"_");
     existe_deja = true;
    };
  
   // traitement:
   if (!existe_deja)
    {tab_Daa.Change_taille(taille_initiale+1); TypeQuelconque_enum_etendu::taillTab = tab_Daa.Taille();
     int nbenumddl = ClassPourEnumTypeQuelconque::NombreEnumTypeQuelconque();
     tab_Daa(taille_initiale+1).nom = no ;
     tab_Daa(taille_initiale+1).enu = enu;
     tab_Daa(taille_initiale+1).type_grandeur = type_grandeur;
     tab_Daa(taille_initiale+1).posi_nom = nbenumddl + taille_initiale + 1;
     // on met un drapeau global à jour
     retour = tab_Daa(taille_initiale+1);
    };
  // retour
  return retour;
 };


//// retourne le type de grandeur auquel appartient le typeQuelconque  étendue
//EnumTypeGrandeur TypeQuelconque_enum_etendu::TypeDeGrandeur() const
// { int nbenumddl = ClassPourEnumTypeQuelconque::NombreEnumTypeQuelconque();
//   if (nom=="-")
//     {// cas d'un ddl pur
//      return Type_de_grandeur_associee(enu);
//      }
//   else // pour l'instant retourne rien, histoire de provoqué une erreur
//     return RIEN_TYPEGRANDEUR;
////
////
////   if (((posi_nom >=1+nbenumddl)&&(posi_nom<=24+nbenumddl)) ||
////            ((posi_nom >=34+nbenumddl)&&(posi_nom<=39+nbenumddl)) ||
////            ((posi_nom >=43+nbenumddl)&&(posi_nom<=72+nbenumddl)))
////     {return TENSEURBB;}
////   else
////     {return SCALAIRE;};
//  };

// test pour savoir si le nom passer en paramètre est valide
// ramne vrai si no correspond  un EnumTypeQuelconque  ou
// s'il correspond  un type dérivé
bool TypeQuelconque_enum_etendu::VerifExistence(string rep)
  { // tout d'abord on vrifie pour les EnumTypeQuelconque
    if (Existe_typeQuelconque(rep.c_str())) return true;
    // maintenant vrification des types drives
    for (int i=1;i<=taillTab;i++)
     { if (tab_Daa(i).nom == rep)
         return true;
      };
    return false;  
   };
   
// récupération d'un TypeQuelconque_enum_etendu correspondant  un string
TypeQuelconque_enum_etendu TypeQuelconque_enum_etendu::RecupTypeQuelconque_enum_etendu(string rep)
  { // tout d'abord on balaie les EnumTypeQuelconque
    if (Existe_typeQuelconque(rep.c_str()))
      { // recup du ddl 
        EnumTypeQuelconque en = Id_nomTypeQuelconque (rep.c_str());
        TypeQuelconque_enum_etendu a(en);
        // retour
        return a;
        } 
    // cas des types dérivées
    for (int i=1;i<=taillTab;i++)
     { if (tab_Daa(i).nom == rep)
         return tab_Daa(i);
      };
    cout << "\n erreur il n'existe pas de type de ddl etendue correspondant  "
         << rep << " !!!!!";
    cout << "\n TypeQuelconque_enum_etendu RecupTypeQuelconque_enum_etendu(string rep)"
         << endl;
    Sortie(1);
    // pour taire le compilo
    TypeQuelconque_enum_etendu a;
    return a;  
   };

// transformation d'une liste d'EnumTypeQuelconque en TypeQuelconque_enum_etendu
List_io <TypeQuelconque_enum_etendu> TypeQuelconque_enum_etendu::TransfoList_io(const  List_io <EnumTypeQuelconque> &  li)
  { List_io <TypeQuelconque_enum_etendu> ret;
    List_io <EnumTypeQuelconque>::const_iterator ii,iifin= li.end();
    for (ii = li.begin();ii != iifin; ii++)
       ret.push_back(TypeQuelconque_enum_etendu(*ii));
    return ret;
   }     

// transformation d'un tableau d'numration en un tableau de TypeQuelconque_enum_etendu
Tableau < TypeQuelconque_enum_etendu > TypeQuelconque_enum_etendu::TransfoTableau(const Tableau <EnumTypeQuelconque> & tab)
    { int taille = tab.Taille();
      Tableau < TypeQuelconque_enum_etendu > taa(taille);
      for (int i=1;i<= taille;i++)
        taa(i) = TypeQuelconque_enum_etendu(tab(i));
      return taa;
     };   
      
// test si un élément existe dans une liste donnée
bool TypeQuelconque_enum_etendu::Existe_dans_la_liste
           (const List_io <TypeQuelconque_enum_etendu> & lis, const TypeQuelconque_enum_etendu& dd)
 { List_io < TypeQuelconque_enum_etendu>::const_iterator retour_existe =
   find(lis.begin(),lis.end(),dd);
   if (retour_existe != lis.end())
      return true;
   else // 
   return false;   
 };               

// lecture avec création éventuelle si le type n'existe pas
TypeQuelconque_enum_etendu TypeQuelconque_enum_etendu::Lecture_avec_creation_eventuelle(istream & ent)
{// on lit les entités
 string no; EnumTypeQuelconque enu;EnumTypeGrandeur type_grandeur;
 ent >> no >> enu >> type_grandeur;
 // on regarde si le type existe
 if (VerifExistence(no))
  { // oui on récupère
    TypeQuelconque_enum_etendu a = RecupTypeQuelconque_enum_etendu(no);
    // on vérifie que les types associés sont correctes
    // si oui on ramène la grandeur
    if ((a.enu == enu) && (a.type_grandeur == type_grandeur))
      return a;
    else
     {cout << "\n erreur en lecture du type quelconque "
           << no << " ";
      if (a.enu != enu)
        cout << " l'enumere "<< NomTypeQuelconque(a.enu) << " existant "
             << " est different de celui lu "<< NomTypeQuelconque(enu) << " ";
      if (a.type_grandeur != type_grandeur)
        cout << " le type de grandeur "<< NomTypeGrandeur(a.type_grandeur) << " existant "
             << " est different de celui lu "<< NomTypeGrandeur(type_grandeur) << " ";
      Sortie(1);
     };
  }
 else // sinon on crée
  { TypeQuelconque_enum_etendu a = Ajout_un_TypeQuelconque_enum_etendu(enu,no,type_grandeur);
    return a;
  };
};


      





