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

#include "OrdreVisu.h"
#include "CharUtil.h"
#include <iomanip>

// définition des données statiques
list <string> OrdreVisu::list_nom_coordinate;
list < list <Coordonnee > >  OrdreVisu::list_coordinate;
string OrdreVisu::nom_base_couleur= "base_couleur"; // utilisé dans déformée

// ----------- definition du type énuméré -------------

// Retourne le nom d'un type d'incrément a partir de son identificateur de
// type enumere id_TypeIncre correspondant
string OrdreVisu::Nom_TypeIncre (const OrdreVisu::EnumTypeIncre id_nom)
{string  result="";
	switch (id_nom)
	{ case PREMIER_INCRE :    result="PREMIER_INCRE";break;
		 case INCRE_COURANT :    result="INCRE_COURANT";break;
		 case DERNIER_INCRE :    result="DERNIER_INCRE";break;
		 default :
		   {cout << "\nErreur : valeur incorrecte du type EnumTypeIncre !\n";
			cout << "OrdreVisu::Nom_TypeIncre (const OrdreVisu::EnumTypeIncre id_nom) \n";
			Sortie(1);}
	};
	return result;
};

// Retourne l'identificateur de type enumere associe au nom du type d'incrément
OrdreVisu::EnumTypeIncre OrdreVisu::Id_nom_TypeIncre (const string nom)
{EnumTypeIncre result;
	if ( nom == "PREMIER_INCRE")result=PREMIER_INCRE;
	else if ( nom == "INCRE_COURANT" )result=INCRE_COURANT;
	else if ( nom == "DERNIER_INCRE" )result=DERNIER_INCRE;
    else
	{  cout << "\nErreur : nom du degre de type d'increment inconnu ! ("
		     << nom << ") \n";
		cout << "EnumTypeIncre OrdreVisu::Id_nom_TypeIncre (const string nom_TypeIncre) \n";
		Sortie(1);
	};
	return result;
};	

// ----------- fin definition du type énuméré -------------

// CONSTRUCTEURS :
     // par defaut
OrdreVisu::OrdreVisu () :
  commentaire_sommaire(),explication_detail()
  ,ordre(),actif(false)
  {}; 
     // permettant la définition de l'affichage
OrdreVisu::OrdreVisu
     (const string& comment_som, const string& explication, const string& ordre):
  commentaire_sommaire(comment_som),explication_detail(explication)
  ,ordre(ordre),actif(false)
    {}
     // constructeur de copie 
OrdreVisu::OrdreVisu (const OrdreVisu& ord) :
  commentaire_sommaire(ord.commentaire_sommaire),explication_detail(ord.explication_detail)
  ,ordre(ord.ordre),actif(ord.actif)
    {};
               
    // DESTRUCTEUR :
OrdreVisu::~OrdreVisu () 
   {};  
    
    // METHODES PUBLIQUES :
// affichage de l'ordre
void OrdreVisu::Affiche_ordre()
  { // affichage de l'ordre s'il n'est pas vide
    if (commentaire_sommaire.size() != 0)
      cout << "\n"  << setiosflags (ios::right) << commentaire_sommaire << ": " 
         << setiosflags (ios::right) << setw(10) << ordre ;
//      cout << "\n" << setw(50) << setiosflags (ios::right) << commentaire_sommaire << ": " 
//         << setiosflags (ios::right) << setw(10) << ordre ;
    };
// affichage de l'explication détaillée
void OrdreVisu::Explication_detaillee()
   { cout << "\n" << explication_detail;};
    
// initialisation : permet d'initialiser les différents paramètres de l'ordre
// lors d'un premier passage des différents incréments
// en virtuelle, a priori est défini si nécessaire dans les classes dérivées
void OrdreVisu::Initialisation(ParaGlob * ,LesMaillages *,LesReferences*
                      ,LesLoisDeComp* ,DiversStockage*,Charge*,LesCondLim*,LesContacts*
                      ,Resultats*,EnumTypeIncre ,int 
                      ,const map < string, const double * , std::less <string> >&
                      ,const List_io < TypeQuelconque >& listeVecGlob
                      ,bool) 
   { OrdreVisu::Mise_zero_coordo();
     // faire attention, car tous les incréments ne sont pas passé systématiquement en revue
     // donc l'initialisation se fait sur un choix d'incréments choisit par l'utilisateur
   };
   
// execution de l'ordre
// en virtuelle, a priori est défini dans les classes dérivées
// unseul_incre : indique si oui ou non il y a un seul increment à visualiser
void OrdreVisu::ExeOrdre(ParaGlob * ,const Tableau <int>&   ,LesMaillages *,bool,LesReferences*
                      ,LesLoisDeComp* ,DiversStockage*
                      ,Charge*,LesCondLim*,LesContacts*,Resultats*,UtilLecture & ,OrdreVisu::EnumTypeIncre
                      ,int , bool,const map < string, const double * , std::less <string> >&
                      ,const List_io < TypeQuelconque >& listeVecGlob)
   {  // pour éviter l'affichage suivant il faut que la fonction soit surchargée 
      cout <<  "\n actuellement aucune action n'est implantee pour cet ordre "
           <<  "\n OrdreVisu::ExeOrdre( ";
      Affiche_ordre();
    };
    
// retour vrai  si l'ordre proposée est celui de l'instance
bool OrdreVisu::OrdreVrai(const string& reponse)
 { // tout d'abord s'il n'y a rien dans la réponse, retour faux
   if (reponse.length () == 0) return false;
   // si il n'y a pas d'ordre possible, réponse faux également
   if (ordre.length() == 0) return false;
   // transformation des caractères en minuscule
   string rep = Minuscules(reponse);
   // test si l'on trouve l'ordre en question
   if (rep.find(ordre) == string::npos)
         return false;
   else
         return true;  
  };
        
// choix de l'ordre, cet méthode peut entraîner la demande d'informations
// supplémentaires si nécessaire. qui sont ensuite gérer par la classe elle même
void OrdreVisu::ChoixOrdre()
   {  actif = true;
   };
    
// lecture des paramètres de l'ordre dans un flux
void OrdreVisu::Lecture_parametres_OrdreVisu(UtilLecture & )
   {  // pour éviter l'affichage suivant il faut que la fonction soit surchargée 
      cout <<  "\n " << commentaire_sommaire 
           << " actuellement aucune lecture de parametre n'est implantee pour cet ordre "
           <<  "\n OrdreVisu::Lecture_parametres_OrdreVisu( ";
      Affiche_ordre();
   };

    // écriture des paramètres de l'ordre dans un flux
void OrdreVisu::Ecriture_parametres_OrdreVisu(UtilLecture & )
   {  // pour éviter l'affichage suivant il faut que la fonction soit surchargée 
      cout <<  "\n " << commentaire_sommaire 
           << " actuellement aucune ecriture de parametre n'est implantee pour cet ordre "
           <<  "\n OrdreVisu::Ecriture_parametres_OrdreVisu( ";
      Affiche_ordre();
   };
    
       
//============================== méthodes protégées ============================

// ordonne une liste, supprime les doublons et finalement l'affiche à l'écran
void OrdreVisu::Propre_liste(list<int>& lis_sor)
  {        // on ordonne la liste puis on supprime les doublons enfin on l'afficher
           list<int>::iterator ik,ikfin;
           lis_sor.sort();  // on ordonne la liste
           lis_sor.unique(); // suppression des doublons 
           // affichage
           cout << "\n liste finale : ";
           ikfin = lis_sor.end();
           for (ik=lis_sor.begin();ik!=ikfin;ik++)
             cout << *ik << " ";
           cout << "\n";  

   };

// mise a zéro des lists de coordonnées
void OrdreVisu::Mise_zero_coordo()
   { if (list_nom_coordinate.size() != 0)
       { list_nom_coordinate.erase(list_nom_coordinate.begin(),list_nom_coordinate.end());
         list_coordinate.erase(list_coordinate.begin(),list_coordinate.end());
       };
   };
     
// lecture des paramètres de l'ordre général dans un flux
void OrdreVisu::Lect_para_OrdreVisu_general(UtilLecture & entreePrinc)
  { entreePrinc.NouvelleDonneeCVisu(); // on passe un enregistrement
    string nom;
    // essaie de lecture
    try 
     { (*entreePrinc.entCVisu) >> nom; // lecture de l'identificateur
       if (nom != "actif")
         { cout << "\n ERREUR dans la lecture de l'activite de l'ordre, on le met inactif par defaut";
           actif = false;
          }
       else
         { (*entreePrinc.entCVisu) >> actif;
           entreePrinc.NouvelleDonneeCVisu(); // on passe un enregistrement
          };
      }   
    catch (ErrSortieFinale)
         // cas d'une direction voulue vers la sortie
         // on relance l'interuption pour le niveau supérieur
       { ErrSortieFinale toto;
         throw (toto);
       }
    catch (...)// erreur de lecture
       {  cout << "\n Erreur en lecture de l'activite de l'ordre a partir d'un fichier .CVisu,"
               << " , on le met inactif par defaut !! ";
          actif = false;
       };
    };
    
// écriture des paramètres de l'ordre dans un flux
void OrdreVisu::Ecrit_para_OrdreVisu_general(UtilLecture & entreePrinc)
  { // écriture de l'activité de l'ordre
    ostream & sort = (*(entreePrinc.Sort_CommandeVisu()));
    sort << "\n actif " << actif << "   # <0 ou 1> indique si l'ordre est actif ou non ";
  };