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

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

    // CONSTRUCTEURS :
// par defaut
ChoixDesMaillages_vrml::ChoixDesMaillages_vrml () :
   OrdreVisu("............choix du ou des maillages a visualiser"  // de 15 à 65
    ,"definition des numeros de maillage que l'on souhaite visualiser ","cmv")
   ,lis_sor(),nb_maillage(NULL)          
     {}; 
     
     // constructeur de copie 
ChoixDesMaillages_vrml::ChoixDesMaillages_vrml (const ChoixDesMaillages_vrml& ord) :
    OrdreVisu(ord),lis_sor(ord.lis_sor),nb_maillage(ord.nb_maillage) 
      {};
               
    // DESTRUCTEUR :
ChoixDesMaillages_vrml::~ChoixDesMaillages_vrml () 
     {};  
    
    // METHODES PUBLIQUES :

// choix de l'ordre
void ChoixDesMaillages_vrml::ChoixOrdre()
   { // demande de précision
     bool choix_valide = false;
     while (!choix_valide)
      { cout << "\n liste actuelle des maillages : ";
        list <int>::iterator ikk,ikkfin=lis_sor.end();
        for (ikk=lis_sor.begin();ikk!=ikkfin;ikk++) cout << *ikk << " ";
        cout << "\n liste des maillage disponibles : " 
             << " de 1 à " << *nb_maillage;
        cout << "\n parametre par defaut ? tous les maillages "
             << "   (rep 'o') pour accepter sinon autre ";
        string rep;rep = lect_return_defaut(false,"o"); cout << " (lue: " << rep << ") " << endl;
        if (rep == "o")
          { // on rempli la liste avec tous les numéros de maillage 
            for (int i=1;i<= *nb_maillage;i++)
                   lis_sor.push_back(i);
            choix_valide = true;}
        else 
          { // définition des maillages 
            // On regarde tout d'abord si l'on veut des maillages en plus ou si l'on veut que 
            // les maillages que l'on va indiquer
            cout << "\n voulez-vous effacer la liste actuelle qui est : ";
            list <int>::iterator ik,ikfin=lis_sor.end();
            for (ik=lis_sor.begin();ik!=ikfin;ik++) cout << *ik << " ";
            cout << "\n rep 'o' pour effacer sinon autre (defaut)? ";
            rep = lect_return_defaut(false,"n"); cout << " (lue: " << rep << ") " << endl;
            if (rep == "o") lis_sor.erase(lis_sor.begin(),lis_sor.end());
            cout << "\n entree des numeros de maillage   "
                 << "\n (un numero negatif signifie que l'on ne veut que les frontieres du maillage) : "
                 << "\n un seul maillage              rep : 1 "
                 << "\n un intervalle de maillages    rep : 2 "
                 << "\n une liste de maillage         rep : 3 "
                 << "\n aucune action (defaut)        rep : o (ou 0) ";
            cout << "\n un premier chiffre negatif indique que c'est un maillage à retirer (si possible)"
                 << "\n par contre s'il est positif c'est un maillage a ajouter (s'il n'existe pas deja)"
                 << "\n les increments sont systematiquement ordonne en fin de traitement \n rep ? ";
            rep = lect_return_defaut(false,"0"); cout << " (lue: " << rep << ") " << endl;
           
            if (rep== "1")
              {  cout << "\n numero du maillage ? : ";
                 int irep; irep=(int)lect_double();
                 // on vérifie que le numéro de maillage est possible si oui on enregistre
                 if ((abs(irep) > 0) && (abs(irep)<= *nb_maillage))
                  {if (irep > 0)
                     lis_sor.push_back(irep); // ajout
                   else
                     lis_sor.remove(abs(irep)); // suppression s'il existe
                   choix_valide = true;
                   }
               }
            else if (rep== "2")
              {  cout << "\n numero de depart et numero de fin (deux entiers):  ";
                 int irep1,irep2; cin >> irep1 >> irep2;
                 std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );// purge de cin
                 // on vérifie que le numéro de maillage est possible si oui on enregistre
                 if ((abs(irep1) > 0) && (abs(irep1)<= *nb_maillage)
                  && (abs(irep2) > 0) && (abs(irep2)<= *nb_maillage))
                   { // enregistrement
                     if (irep1 > 0) // cas d'un ajout
                       for (int i=abs(irep1);i<= abs(irep2);i++)
                         lis_sor.push_back(i);
                     else // cas ou on retire
                       for (int i=abs(irep1);i<= abs(irep2);i++)    
                         lis_sor.remove(abs(i)); 
                     choix_valide = true;
                    }
                 else
                   { cout << "erreur de bornes  ";
                     choix_valide = false;
                    }
               }
            else if (rep == "3")
              {  cout << "\nl'entree d'une liste de numeros de maillages s'effectue numero par numero: ";
                 int irep = -1;
                 do 
                   { cout << "\n un  numero ? puis return (ou 0 pour finir): " << endl ;
                     irep=(int)lect_double();
                     // vérification si le numéro est acceptable
                     if ((abs(irep) > 0) && (abs(irep)<= *nb_maillage))
                       {if (irep > 0)
                          lis_sor.push_back(irep); // ajout
                        else
                          lis_sor.remove(abs(irep)); // suppression s'il existe
                        choix_valide = true;
                        }
                     else if (irep !=0)
                       { cout << "\n numero non acceptable (doit etre compris entre 1 et " << *nb_maillage;
                         cout << "\n recommencez ";
                         irep = -20;
                        }
                     } while (irep!= 0);
                 }     
            else if ((rep =="o")||(rep =="0"))
              { 
                choix_valide = true;
               }
            else 
              { cout << "\n choix non valide !!  ";
                choix_valide = false;
               }    
            }
          }  
       // on ordonne la liste puis on supprime les doublons enfin on l'afficher
       Propre_liste(lis_sor);
       // appel de la méthode de la classe mère
       OrdreVisu::ChoixOrdre();    
     };     
            
// initialisation du nombre de maillages possibles
// et définition de tous les maillages par défaut dans la liste des maillages
// a visualiser
void ChoixDesMaillages_vrml::Init_nb_maill(int& nb_maillage_poss)
   {nb_maillage = & nb_maillage_poss; 
    // définition de la liste de sortie
    lis_sor.erase(lis_sor.begin(),lis_sor.end());
    for (int i=1;i<= *nb_maillage;i++)
        lis_sor.push_back(i);
   }; 
    
// lecture des paramètres de l'ordre dans un flux
void ChoixDesMaillages_vrml::Lecture_parametres_OrdreVisu(UtilLecture & entreePrinc)
 { // si dans le flot il existe l'identificateur adoc on lit sinon on passe
   if (strstr(entreePrinc.tablcarCVisu,"debut_choix_maillage")!=NULL)
     {// sauvegarde de la liste actuelle
      list <int> liste_sauve = lis_sor;     
      // essaie de lecture
      try 
        { string nom; 
          (*entreePrinc.entCVisu)  >> nom ;
          if (nom != "debut_choix_maillage")
            { cout << "\n Erreur en lecture de la liste de maillage à visualiser a partir d'un fichier .CVisu,"
                   << " le premier enregistrement doit etre le mot clef: debut_choix_maillage "
                   << " on ne tiens pas compte  de la liste fournie !! ";
              }
          else
           { // appel de l'ordre de la classe mère
             OrdreVisu::Lect_para_OrdreVisu_general(entreePrinc);
             // on efface la liste actuelle
             lis_sor.erase(lis_sor.begin(),lis_sor.end());
             // lecture de la liste demandée
             int compteur=0; // pour éviter une boucle infinie
             while (compteur < 1000000)
               { (*entreePrinc.entCVisu) >> nom; compteur++;
                 if (nom != "fin_choix_maillage")
                   { lis_sor.push_back(ChangeEntier(nom));}
                 else break;
                }
            }       
         }    
      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 la liste de maillage à visualiser a partir d'un fichier .CVisu,"
               << " on ne tiens pas compte  de la liste fournie !! ";
          lis_sor=liste_sauve; // récup de la liste sauvée
          if (ParaGlob::NiveauImpression() >= 4)     
             cout  << "\n ChoixDesMaillages_vrml::Lecture_parametres_OrdreVisu(..";
        }
      // on passe à un nouvel enregistrement
      entreePrinc.NouvelleDonneeCVisu();
      }  
  };

// écriture des paramètres de l'ordre dans un flux
void ChoixDesMaillages_vrml::Ecriture_parametres_OrdreVisu(UtilLecture & entreePrinc)
 { // récup du flot  
   ostream & sort = (*(entreePrinc.Sort_CommandeVisu()));
   // on commente le fonctionnement
   sort << "\n #  ----------------------------- choix des maillages a visualiser: ---------------- "
        << "\n #  la liste est facultative, par defaut la visualisation concerne le premier maillage";
   sort << "\n debut_choix_maillage #  un mot cle de debut,";        
   // appel de l'ordre de la classe mère
   OrdreVisu::Ecrit_para_OrdreVisu_general(entreePrinc);
   // puis les paramètres     
   sort << "\n #  une liste d'entiers , puis <fin_choix_maillage>, sur une meme ligne"
        << "\n";
   // on sort la liste des maillage à visualiser
   list<int>::const_iterator ili,ilifin=lis_sor.end();
   for (ili=lis_sor.begin();ili!=ilifin;ili++)
       sort << " " << (*ili);
   sort << " fin_choix_maillage \n";    
  };