// 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 "AlgoInformations.h"

// CONSTRUCTEURS :
AlgoInformations::AlgoInformations () : // par defaut
   Algori()
  {  };   
     
// constructeur en fonction du type de calcul et du sous type
// il y a ici lecture des parametres attaches au type
AlgoInformations::AlgoInformations (const bool avec_typeDeCal
            ,const list <EnumSousTypeCalcul>& soustype
            ,const list <bool>& avec_soustypeDeCal
            ,UtilLecture& entreePrinc) :
         Algori(INFORMATIONS,avec_typeDeCal,soustype,avec_soustypeDeCal,entreePrinc)
  { // lecture des paramètres attachés au type de calcul (ici aucun)
    switch (entreePrinc.Lec_ent_info())
    { case 0 : 
       {// pour signaler à Algori qu'il n'y a pas eu de lecture de paramètre
        deja_lue_entete_parametre=0; 
        // puis appel de la méthode de la classe mère 
        Algori::lecture_Parametres(entreePrinc); break;}
      case -11 : // cas de la création d'un fichier de commande
       { Info_commande_parametres(entreePrinc); break;}
      case -12 : // cas de la création d'un schéma XML, on ne fait rien à ce niveau
       {  break;}
      default:
        Sortie(1); 
     }  
   };
      
// constructeur de copie
AlgoInformations::AlgoInformations (const AlgoInformations& algo):
  Algori(algo)
    {};

// destructeur   
AlgoInformations::~AlgoInformations ()
  {
   }; 

// execution de l'algorithme 
void AlgoInformations::Execution(ParaGlob * p,LesMaillages * lesMail
               ,LesReferences* lesRef,LesCourbes1D* lesCourbes1D,LesFonctions_nD* lesFonctionsnD
               ,VariablesExporter* varExpor,LesLoisDeComp* lesLoisDeComp, DiversStockage* divStock
               ,Charge* charge,LesCondLim* lesCondLim,LesContacts* lesContacts,Resultats* resultats)
  {
  
   tempsInitialisation.Mise_en_route_du_comptage(); // temps cpu
   Transfert_ParaGlob_ALGO_GLOBAL_ACTUEL(INFORMATIONS); // transfert info
   lesMail->Travail_tdt();
   lesMail->Init_Xi_t_et_tdt_de_0();
   // mise à jour au cas où
   Algori::MiseAJourAlgoMere(p,lesMail,lesRef,lesCourbes1D,lesFonctionsnD,varExpor,lesLoisDeComp,divStock
                           ,charge,lesCondLim,lesContacts,resultats);
   // renseigne les variables définies par l'utilisateur via les valeurs déjà calculées par Herezh
   varExpor->RenseigneVarUtilisateur(*lesMail,*lesRef);
   lesMail->CalStatistique(); // calcul éventuel de statistiques
   // on définit le type de  calcul a effectuer :
   if ( soustypeDeCalcul->size()==0 )
      // cas où il n'y a pas de sous type, on fait le calcul 
      // de toutes les cas possibles
       cout << "\n rien pour l'instant (information)\n";
   else 
      // on boucle sur tous les sous_types
     { list <EnumSousTypeCalcul>::const_iterator ili,ili_fin = soustypeDeCalcul->end();
       list <bool>::const_iterator ila;
       for (ili = soustypeDeCalcul->begin(),ila = avec_soustypeDeCalcul->begin();
            ili!=ili_fin;ili++,ila++)
         if (*ila) // cas où le sous type est valide  
          { if ( (*ili) == frontieres )
               // cas du calcul des frontières
              { 
               cout << "\n================================================================="
                    << "\n                      calcul des frontieres "
                    << "\n=================================================================";
               if (ParaGlob::NiveauImpression() >= 4)
                    cout << " \n debut de la creation des elements frontieres " << endl;
               // on calcul les frontières si elles n'existent pas encore
               lesMail->CreeElemFront();
               if (ParaGlob::NiveauImpression() >= 4)
                    cout << " \n fin de la creation des elements frontieres " << endl;
              }
            else if ( (*ili) == creation_reference )
              // cas de l'extrusion d'un maillage 2D en 3D
              {
                 cout << "\n================================================================="
                      << "\n|             creation interactive de references                |"
                      << "\n================================================================="
                      << endl;
        
                 // l'objectif est de créer des listes de références suivant différants critères
                 lesMail->CreationInteractiveListesRef(lesRef);
                 // -----  sort les informations sur fichiers
                 // Affichage des donnees des maillages dans des fichiers dont le nom est construit 
                 // à partir du nom de chaque maillage au format  ".her" et ".lis"
                 lesMail->Affiche_maillage_dans_her_lis(TEMPS_0,*lesRef,-1);
              }
            else if ( (*ili) == calcul_geometrique )
             { // 1) affichage
               cout  << "\n================================================================="
                     << "\n|               calculs geometriques                            |"
                     << "\n================================================================="
                     << endl;
               // choix en fonction de la demande de l'utilisateur
               bool choix_valide = false;

               while (!choix_valide)
                 { cout << "\n ===========        choix du calcul              ==============="
                        << "\n distance initiale entre deux noeuds                  (rep  dN )"
                        << "\n fin                                                  (rep   f )";
                   string rep;
                   cout << "\n reponse ? "; rep = lect_return_defaut(false,"f");
                   string nom_mail_ref(" ");
                   if (rep == "dN") // distance entre deux noeuds
                     { int nb_mail = lesMail->NbMaillage();
                       // premier noeud
                       bool c_valide = false;
                       int cas = 0;// init
                       int num_mail_1=1; int num_noeu_1=0;
                       bool fin_traitement=false;
                        cout << "\n --- premier noeud: ------ ";
                       if (nb_mail > 1)
                        {while (!c_valide)
                          { cout << "\n nom du maillage                   -> rep : nom "
                                 << "\n numero du maillage                -> rep : num "
                                 << "\n  arret                            -> rep : fin (ou f) ";
                            string reponse;
                            cout << "\n reponse ? ";reponse = lect_return_defaut(false,"f"); cout << " lue: "<< reponse;
                            if (reponse == "nom") {cas = 1;c_valide=true;}
                            else if (reponse == "num") {cas = 2;c_valide=true;}
                            else if ((reponse == "fin")||(reponse == "f")) {cas = 0;c_valide=true;}
                            else { cout <<"\n reponse non utilisable, recommencer ";c_valide=false;};
                          };
                         switch (cas)
                          {case 1 : { string nom_mail; cout << " nom? "; nom_mail = lect_chaine();
                                      num_mail_1= lesMail->NumMaillage(nom_mail); break;
                                    }
                           case 2 : { string nom_mail; cout << "\n numero "; num_mail_1 = (int) lect_double();
                                      break;
                                    }

                           default: break;
                          };
                         // vérif de l'existance
                         if ( (num_mail_1 < 1) || (num_mail_1 > nb_mail))
                           {cout << "\n non !! ce maillage n'existe pas !! ";
                            fin_traitement = true;
                           };
                        };
                       if (!fin_traitement)
                         { cout << "\n numero du noeud 1 ? "; num_noeu_1 = (int) lect_double();;
                           int NBN = lesMail->Nombre_noeud(num_mail_1);
                           if ((num_noeu_1 < 1 ) || (num_noeu_1 > NBN))
                             {cout << "\n non !! ce noeud n'existe pas !! ";
                              fin_traitement = true;
                             };
                         };
                       // second noeud
                       c_valide = false;
                       cas = 0;// init
                       cout << "\n --- second noeud: ------ ";
                       int num_mail_2=1; int num_noeu_2=0;
                       if (nb_mail > 1)
                        {while (!c_valide)
                           { cout << "\n nom du maillage                   -> rep : nom "
                               << "\n numero du maillage                -> rep : num "
                               << "\n  arret                            -> rep : fin (ou f) ";
                          string reponse;
                          cout << "\n reponse ? ";reponse = lect_return_defaut(false,"f"); cout << " lue: "<< reponse;
                          if (reponse == "nom") {cas = 1;c_valide=true;}
                          else if (reponse == "num") {cas = 2;c_valide=true;}
                          else if ((reponse == "fin")||(reponse == "f")) {cas = 0;c_valide=true;}
                          else { cout <<"\n reponse non utilisable, recommencer ";c_valide=false;};
                        };
                         switch (cas)
                           {case 1 : { string nom_mail; cout << " nom? ";  nom_mail = lect_chaine();
                                       num_mail_2= lesMail->NumMaillage(nom_mail); break;
                                     }
                            case 2 : { string nom_mail; cout << "\n numero ";  num_mail_2 = (int) lect_double();
                                       break;
                                     }

                            default: break;
                           };
                         if ( (num_mail_2 < 1) || (num_mail_2 > nb_mail))
                           {cout << "\n non !! ce maillage n'existe pas !! ";
                            fin_traitement = true;
                           };
                        };
                       if (!fin_traitement)
                         { cout << "\n numero du noeud 2 ? ";  num_noeu_2 = (int) lect_double();
                           int NBN = lesMail->Nombre_noeud(num_mail_2);
                           if ((num_noeu_2 < 1 ) || (num_noeu_2 > NBN))
                             {cout << "\n non !! ce noeud n'existe pas !! ";
                              fin_traitement = true;
                             };
                         };
                      
                       // on calcul la distance
                       if (!fin_traitement)
                         {Noeud& noe1 = lesMail->Noeud_LesMaille(num_mail_1,num_noeu_1);
                          Noeud& noe2 = lesMail->Noeud_LesMaille(num_mail_2,num_noeu_2);
                          Coordonnee co1= noe1.Coord0();
                          Coordonnee co2= noe2.Coord0();
                          double distance = (co2-co1).Norme();
                          cout << "\n distance = "<<distance<<endl;
                         };
                          
                       }
                   else if ((Minuscules(rep) == "fin") || (Minuscules(rep) == "f"))
                     choix_valide = true;
                   else
                     cout << "\n la réponse : " << rep << " n'est pas utilisable, recommencez !";         
                 };
             }
          };
     };
    // pour des pb de sortie de résultat qui peuvent bloquer on met à zéro les degrés
    // de liberté
    lesMail->ZeroDdl(true);
    tempsInitialisation.Arret_du_comptage(); // temps cpu

   };

//----------------------------------- fonctions internes -------------------------


