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

/************************************************************************
 *     DATE:        19/01/2001                                          *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *     BUT:  une classe qui permet de définir des identificateurs de    *
 *           grandeurs secondaires associées à des Enum_ddl ddl de base.*
 *           Ces grandeurs ne sont pas vraiment des ddl, mais ils s'en  *
 *           déduisent. Ainsi pour ne pas alourdir le type Enum ddl     *
 *           on crée cette classe associée. Elle est prévue en particu- *
 *           lier pour gérer les sorties de résultats.                  *
 *           les éléments sont ordonnés selon la règle suivante :       *
 *           si c'est un Enum_ddl pur ->  ordre de l'Enum               *
 *           si c'est un élément de tab_Dee -> ordre dans tab_Dee       *
 *           + maxi des Enum_ddl                                        *
 *           lorsqu'il s'agit d'un enum_ddl tout simple, dans ce cas    *
 *           Non_vide == true                                           *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 ************************************************************************/
 
#ifndef DDL_ENUM_ETENDUE_H
#define DDL_ENUM_ETENDUE_H

#include "Enum_ddl.h"
#include <string.h>
#include "List_io.h"
#include <iomanip>
#include <algorithm>
#include "Enum_TypeQuelconque.h"

/** @defgroup Group_Ddl_enum_etendu
*
*     BUT:  une classe qui permet de définir des identificateurs de
*           grandeurs secondaires associées à des Enum_ddl ddl de base.
*           Ces grandeurs ne sont pas vraiment des ddl, mais ils s'en
*           déduisent. Ainsi pour ne pas alourdir le type Enum ddl
*           on crée cette classe associée. Elle est prévue en particu-
*           lier pour gérer les sorties de résultats.
*           les éléments sont ordonnés selon la règle suivante :
*           si c'est un Enum_ddl pur ->  ordre de l'Enum
*           si c'est un élément de tab_Dee -> ordre dans tab_Dee
*           plus maxi des Enum_ddl
*           lorsqu'il s'agit d'un enum_ddl tout simple, dans ce cas
*           Non_vide == true
*
*
* \author    Gérard Rio
* \version   1.0
* \date       19/01/2001
* \brief       classe qui permet de définir des identificateurs de grandeurs secondaires associées à des Enum_ddl ddl de base.
*
*/

/// @addtogroup Group_Ddl_enum_etendu
///  @{

/// une classe secondaire: définition d'une  classe pour l'initialisation du tableau tab_Dee
/// et de la map qui relie les string et les Ddl_enum_etendu
class Initialisation_tab_Dee { public: Initialisation_tab_Dee(); };
/// @}  // end of group

/// @addtogroup Group_Ddl_enum_etendu
///  @{

/// la classe principale: Ddl_enum_etendu
class Ddl_enum_etendu
{
 // surcharge de l'operator de lecture
  friend istream & operator >> (istream & ent, Ddl_enum_etendu & a)
//    { ent >> a.nom >> a.enu ; return ent;};
    { string no; ent >> no; a=Ddl_enum_etendu(no); return ent;};
  
 // surcharge de l'operator d'ecriture
  friend ostream & operator << (ostream & sort , const Ddl_enum_etendu & a)
//    { sort << a.nom << " " << a.enu << " "; return sort;};
    { if (a.Nom_vide()) sort << " " << Nom_ddl(a.enu); else sort << " " << a.nom; return sort;};

 // permition pour l'initialisation du tableau tab_Dee   
  friend class Initialisation_tab_Dee;
  
  public :
    // CONSTRUCTEURS :
    // constructeur par défaut
    Ddl_enum_etendu(Enum_ddl en = NU_DDL, string no = "-");
    // constructeur fonction d'un string 
    Ddl_enum_etendu( string no );
    // constructeur fonction  d'une chaine
//    Ddl_enum_etendu( char * no );
    // constructeur de copie
    Ddl_enum_etendu(const Ddl_enum_etendu& a) :
         nom(a.nom), enu(a.enu), posi_nom(a.posi_nom)  {};             
    // DESTRUCTEUR :
    ~Ddl_enum_etendu() {};
    
    // METHODES PUBLIQUES :
    
    // surcharge d'affectation
    Ddl_enum_etendu & operator = ( const Ddl_enum_etendu & a)
      { nom = a.nom; enu = a.enu; posi_nom = a.posi_nom; return *this;};
    // surcharge d'égalité
    bool operator == ( const Ddl_enum_etendu & a) const 
      { if (posi_nom == a.posi_nom) return true; else return false;};
    // surcharge de non égalité
    bool operator != ( const Ddl_enum_etendu & a) const 
      { if (posi_nom != a.posi_nom) return true; else return false;};
    // surcharge de comparaison
    bool operator > (const Ddl_enum_etendu & a) const
      { return (posi_nom > a.posi_nom);};
    bool operator >= (const Ddl_enum_etendu & a) const
      { return (posi_nom >= a.posi_nom);};
    bool operator < (const Ddl_enum_etendu & a) const
       { return (posi_nom < a.posi_nom);};
    bool operator <= (const Ddl_enum_etendu & a) const
      { return (posi_nom <= a.posi_nom);};
    
    // récup de l'énumération
    Enum_ddl Enum() const {return enu;};
    // récup du nom
    string Nom() const {return nom;};
    // récup du nom générique (sans les indices de composantes)
    string NomGenerique() const 
      {if (nom=="-"){return string(NomGeneric(enu));} 
       else {return string(nom.substr(1,nom.length()-2));};
       };
    // récup d'un nom, qui est soit le nom de l'enum soit le nom + complet
    // s'il existe
    string Nom_plein() const {return ((nom=="-")? Nom_ddl(enu) : nom );};
    // position donne un numéro équivalent du type énuméré
    int Position() const {return posi_nom;};
    // modification du nom
    // test pour savoir si le nom est vide
    bool Nom_vide() const { if (nom == "-") return true; else return false; };
    // retour le type de grandeur auquel apartient le ddl étendue
    // par exemple : UY : apartiend à un vecteur
    // SIG12 : à un tenseur, TEMP : à un scalaire
    EnumTypeGrandeur TypeDeGrandeur() const;
    
    // test pour savoir si le nom passer en paramètre est valide
    // ramène vrai si no correspond à un Enum_ddl  ou 
    // s'il correspond à un type dérivé : ex contrainte de mise est un type
    // dérivée de contrainte
    static bool VerifExistence(string no)  ;
    // récupération d'un Ddl_enum_etendu correspondant à un string
    static Ddl_enum_etendu RecupDdl_enum_etendu(string to)  ;
    // transformation d'une liste d'Enum_ddl en Ddl_enum_etendu
    static List_io <Ddl_enum_etendu> TransfoList_io(const  List_io <Enum_ddl> &  li) ;
    // transformation d'un tableau d'énumération en un tableau de Ddl_enum_etendu
    static Tableau < Ddl_enum_etendu > TransfoTableau(const Tableau <Enum_ddl> & tab) ; 
    // test si un élément existe dans une liste donnée
    static bool Existe_dans_la_liste
           (const List_io <Ddl_enum_etendu> & lis, const Ddl_enum_etendu& dd) ;     
    // récupération du nombre maximum de ddl étendu existant
    static int NBmax_ddl_enum_etendue() {return taillTab+NbEnum_ddl();};
	   // récup d'un tableau d' enum_ddl_etendue particulier : de force normale et tangentielle
	   // 2 éléments, le premier correspond à "reaction_normale" et le second à "reaction_tangentielle"
	   static const Tableau <Ddl_enum_etendu>& Tab_FN_FT() {return tab_FN_FT;};
 
    // récupération du premier Ddl_enum_etendu du même type : i.e. la première composante
    static Ddl_enum_etendu PremierDdlEnumEtenduFamille(const Ddl_enum_etendu& a);
 
    // création et récupération d'une liste d'enum de grandeurs quelconques équivalentes
    // sous forme de grandeurs évoluées, à la liste de Ddl_enum_etendu passée en argument
    // et d'une liste de ddl_enum_etendu, pour les grandeurs qui n'ont pas d'équivalent
    // retourne également true ou false suivant que toutes les grandeurs ont un équivalent ou pas
    static void Equivalent_en_grandeur_quelconque(const list <Ddl_enum_etendu> & list_enu_etendu
                          , list <EnumTypeQuelconque> & list_enu_quelconque
                          , list <Ddl_enum_etendu> & list_enu_restant);
    // idem mais pour une seule grandeur: ramène l'énum quelconque s'il existe sinon
    // ramène RIEN_TYPEQUELCONQUE
    static EnumTypeQuelconque Equivalent_en_grandeur_quelconque(const Ddl_enum_etendu & enu_etendu);

  protected :  
    // VARIABLES PROTEGEES :
    string nom;
    Enum_ddl enu;
    int posi_nom;  // position du nom  : équivalent à un type énuméré
    
    // on définie le  tableau des Ddl_enum_etendu qui sont valides
    // en variables globales
    static Tableau < Ddl_enum_etendu > tab_Dee; 
    static Initialisation_tab_Dee init_tab_Dee;
    static int taillTab; // taille du tableau tab_Dee
	 
    // tableaux particuliers
    static Tableau <Ddl_enum_etendu> tab_FN_FT; // le tableau des deux ddl etendus
    
    // def de la map qui fait la liaison entre les string et les  Ddl_enum_etendu
    static map < string, int , std::less < string> > map_Ddl_enum_etendu;    
        
   // METHODES PROTEGEES :
    
 };
 /// @}  // end of group

#endif  
