#include <iostream>
#include <list>
#include <vector>

#ifndef GARNIER-GAUTIER-LE-GROS-VIGUIER-AUTOMATE_H_INCLUDED
#define GARNIER-GAUTIER-LE-GROS-VIGUIER-AUTOMATE_H_INCLUDED

using namespace std;

typedef struct Transition;
struct Transition
{
    string symbole; ///Symbole de la transition
    string* arrivee; ///Tableau contenant les etats d'arrivee
};

Transition TransitionCreee(Transition transition, string symbole, string numero, string name, int nb_transi, string type = "x"); ///Permet de creer une transition
Transition TransitionDeter(Transition transition, vector < vector<string> > t_arrivee, int i, int* taille, int& transi); ///Permet de creer une transition dans le cas d'une determinisation

typedef struct Etat;
struct Etat
{
    string nom; ///Nom
    string type; ///Type de l'état : initial (i), terminal(t), initial - terminal (it), normal(n)
    list <Transition> transitions; ///Liste qui représente les symboles et vers lesquels pointent les etats et qui pointent vers les états

};

Etat EtatCree(Etat etat, string name, string typee, int nb_symb, string numero, int nb_transi); ///Permet de creer un etat
Etat EtatDeterm(Etat etat, string name, string typee, vector < vector<string> > t_arrivee, int nb_symb, int* taille, int& transi);///Permet de creer un etat dans le cas d'une determinisation

class Automate
{

    int nb_symb; ///Nombre de symbole dans l'alphabet
    int nb_etats; ///Nombre d'états
    int nb_etats_init; ///Nombre d'états initiaux
    int nb_etats_term; ///Nombre d'états terminaux
    int nb_transi; ///Nombre de transitions
    string* etats_init; ///Stocke les états initiaux
    string* etats_term; ///Stocke les états finaux
    list <Etat> etats; ///Liste des états

public:
    int nb_automate; ///Numéro de l'automate

    Automate(int num_automate); ///Permet de creer un automate
    Automate();
    friend ostream& operator<<(ostream& os, const Automate& aAutomate); ///Surcharge de l'operateur d'affichage
    friend bool isDeterministe(Automate aAutomate); ///Verifie si un automate est deterministe
    friend bool isComplet(Automate aAutomate); ///Verifie si un automate est complet
    friend void Completer(Automate& aAutomate); ///Complete un automate non complet
    friend void Determiniser(Automate aAutomate, Automate& bAutomate); ///Determinise un automate non deterministe
    friend void RecoMot(Automate aAutomate); ///Permet de verifier si un automate reconnait ou pas un mot
};

#endif // GARNIER-GAUTIER-LE-GROS-VIGUIER-AUTOMATE_H_INCLUDED
