#include <iostream>
#include <cstdlib>
#include <string>

#include <vector>

#include "Beloeil-Charbonnel-Dinh-automate.h"
#include "Beloeil-Charbonnel-Dinh-utils.h"
#include "Beloeil-Charbonnel-Dinh-state.h"

/*
 TODO .
    corriger la mise en forme du code
        # Fuck windows ...
    refaire la majorité des commentaires
        # trolol
    préfixé les fichier avec nos nom

*/

int main() {

  std::cout << std::endl << "  ### Projet de MPI ####" << std::endl;
  std::cout << std::endl << "  ## Beloeil Sebastien" << std::endl;
  std::cout << "  ## Thomas Charbonnel" << std::endl;
  std::cout << "  ## Marc Dinh" << std::endl << std::endl;

  int choice = 0;

  std::string mon_fichier;
  bool rechargeAutomate;

  Automate First;

  do {
    rechargeAutomate = false;

    // chargement du fichiers 
    std::
        cout << "  Choississez le fichier que vous voulez charger :" <<
        std::endl;
    std::cout << "  1 | 1   ; " << std::endl;
    std::cout << "  2 | 2   ; ";
    std::cout << "  3 | 3   ; " << std::endl;
    std::cout << "  4 | 4   ; ";
    std::cout << "  5 | 5   ; " << std::endl;
    std::cout << "  6 | 6   ; ";
    std::cout << "  7 | 8   ; " << std::endl;
    std::cout << "  8 | 9   ; ";
    std::cout << "  9 | 12  ; " << std::endl;
    std::cout << " 10 | 13  ; ";
    std::cout << " 11 | 15  ; " << std::endl;
    std::cout << " 12 | 19  ; ";
    std::cout << " 13 | 72  ; " << std::endl;
    std::cout << " 14 | 79  ; ";
    std::cout << " 15 | 80  ; " << std::endl;
    std::cout << " 16 | 85  ; ";
    std::cout << " 17 | 92  ; " << std::endl;
    std::cout << " 18 | 96  ; ";
    std::cout << " 19 | 99  ; " << std::endl;
    std::cout << " 20 | 101 ; ";
    std::cout << " 21 | 102 ; " << std::endl;
    std::cout << " 22 | 103 ; ";
    std::cout << " 23 | 104 ; " << std::endl;
    std::cout << " 24 | 106 ; ";
    std::cout << " 25 | 107 ; " << std::endl;
    std::cout << " 26 | 108 ; ";
    std::cout << " 27 | 109 ; " << std::endl;
    std::cout << " 28 | 110 ; ";
    std::cout << " 29 | 111 ; " << std::endl;
    std::cout << " 30 | 113 ; " << std::endl;
    // ceci a été générer par un script

    secureImput(choice, 0, 30);
    //choice=5;
    switch (choice) {
    case 1:
      mon_fichier = "test/1.txt";
      break;
    case 2:
      mon_fichier = "test/2.txt";
      break;
    case 3:
      mon_fichier = "test/3.txt";
      break;
    case 4:
      mon_fichier = "test/4.txt";
      break;
    case 5:
      mon_fichier = "test/5.txt";
      break;
    case 6:
      mon_fichier = "test/6.txt";
      break;
    case 7:
      mon_fichier = "test/8.txt";
      break;
    case 8:
      mon_fichier = "test/9.txt";
      break;
    case 9:
      mon_fichier = "test/12.txt";
      break;
    case 10:
      mon_fichier = "test/13.txt";
      break;
    case 11:
      mon_fichier = "test/15.txt";
      break;
    case 12:
      mon_fichier = "test/19.txt";
      break;
    case 13:
      mon_fichier = "test/72.txt";
      break;
    case 14:
      mon_fichier = "test/79.txt";
      break;
    case 15:
      mon_fichier = "test/80.txt";
      break;
    case 16:
      mon_fichier = "test/85.txt";
      break;
    case 17:
      mon_fichier = "test/92.txt";
      break;
    case 18:
      mon_fichier = "test/96.txt";
      break;
    case 19:
      mon_fichier = "test/99.txt";
      break;
    case 20:
      mon_fichier = "test/101.txt";
      break;
    case 21:
      mon_fichier = "test/102.txt";
      break;
    case 22:
      mon_fichier = "test/103.txt";
      break;
    case 23:
      mon_fichier = "test/104.txt";
      break;
    case 24:
      mon_fichier = "test/106.txt";
      break;
    case 25:
      mon_fichier = "test/107.txt";
      break;
    case 26:
      mon_fichier = "test/108.txt";
      break;
    case 27:
      mon_fichier = "test/109.txt";
      break;
    case 28:
      mon_fichier = "test/110.txt";
      break;
    case 29:
      mon_fichier = "test/111.txt";
      break;
    case 30:
      mon_fichier = "test/113.txt";
      break;
    default:
      std::cerr << " N'est pas censé arriver" << std::endl;
      return EXIT_FAILURE;
      break;
    }
    std::cout << std::endl;

    if(!First.readFile(mon_fichier)) {
      std::cerr << " Verifier votre fichier. ";
      std::cout << " Rechager ? (0 : Non | 1 : Oui ) : ";
      secureImput(choice, 0, 1);
      if(choice) {
        rechargeAutomate = true;
        continue;
      } else {
        std::cerr << " Aucun automate charger " << std::endl;
        return EXIT_FAILURE;
      }
    }
    // Affichage automate initial
    std::cout << " ########################## " << std::endl;
    std::cout << " ####### Automate 1 ####### " << std::endl;
    std::cout << " ########################## " << std::endl;

    First.printAutomate(1);
    Automate Second = First;

    std::cout << "Appuyer sur une touche pour continuer ...  " << std::endl;
    getchar();
    getchar();


    // Standardisation
    std::cout << " ############################ " << std::endl;
    std::cout << " ####### Automate AFS ####### " << std::endl;
    std::cout << " ############################ " << std::endl;
    Second.isAFS();     // Vérification ET standardisation a defaut
    Second.printAutomate(2);

    std::cout << "Appuyer sur une touche pour continuer ...  " << std::endl;
    getchar();


    // Determinisation
    Automate Third = First;

    std::cout << " ############################ " << std::endl;
    std::cout << " ####### Automate AFD ####### " << std::endl;
    std::cout << " ############################ " << std::endl;

    if(Third.isAFD()) {
      std::cout << std::endl << " L'automate est déterministe. " << std::endl;
      Third.printAutomate(3);
      std::
          cout << std::endl << "Appuyer sur une touche pour continuer; " <<
          std::endl;
      getchar();
    } else {
      std::
          cout << std::endl <<
          " L'automate est non-deterministe : Determinisation ..." << std::endl;
      std::cout << "Appuyer sur une touche pour continuer; " << std::endl;
      getchar();

      Third.AFD();
      Third.printAutomate(3);
    }

    std::cout << " ############################# " << std::endl;
    std::cout << " ####### Automate AFDC ####### " << std::endl;
    std::cout << " #############################" << std::endl;

    // Completion
    Automate Fourth = Third;

    if(Fourth.isAFDC()) {
      std::cout << std::endl << " L'automate est complet ";
      if(Fourth.AFDC(true)) {   // on appelle quand meme la fonction pour savoir si il n'y a pas un etat poubelle implicite
        std::cout << "Appuyer sur une touche pour continuer; " << std::endl;
        getchar();
        std::cout << " Un etat Poubelle Implicite a ete trouver " << std::endl;
        Fourth.printAutomate(4);

      } else {
        Fourth.printAutomate(3);
      }
    } else {
      std::
          cout << " L'automate n'est pas complet, Completion ... " << std::endl;
      Fourth.AFDC(false);
      std::cout << "Appuyer sur une touche pour continuer; " << std::endl;
      getchar();
      Fourth.printAutomate(4);
    }

    std::cout << "Appuyer sur une touche pour continuer; " << std::endl;
    getchar();
    std::cout << " ############################## " << std::endl;
    std::cout << " ####### Automate AFDCM ####### " << std::endl;
    std::cout << " ############################## " << std::endl;

    // Minimisation
    std::cout << std::endl << " Minimisation de l'automate " << std::endl;
    Automate Fifth = Fourth;

    Fifth.AFDCM();

    std::cout << "Appuyer sur une touche pour continuer; " << std::endl;
    getchar();
    Fifth.printAutomate(5);
    std::cout << "Appuyer sur une touche pour continuer; " << std::endl;
    getchar();

    // Lecture du mot
    do {
      std::cout << " Que voulez vous faire ? " << std::endl;
      std::cout << " Lire le mot sur ?  : " << std::endl;
      std::cout << " 1 : AFD " << std::endl;
      std::cout << " 2 : AFDC " << std::endl;
      std::cout << " 3 : AFDCM " << std::endl;
      std::cout << " 0 : Quitter : ";


      secureImput(choice, 0, 3);
      switch (choice) {
      case 1:
        Third.readWord();
        break;
      case 2:
        Fourth.readWord();
        break;
      case 3:
        Fifth.readWord();
        break;
      default:
        break;
      }
    } while(choice);    // on quitte si 0

    std::cout << " Que voulez vous faire ? " << std::endl;
    std::cout << " 0 : quitter | 1 : Recharger un automate : ";

    secureImput(choice, 0, 1);
    if(choice) {
      rechargeAutomate = true;

    }

  } while(rechargeAutomate);

  return EXIT_SUCCESS;
}
