#include "repertoire.h"
#include <iostream>
#include "utilitaires.h"
#include <fstream>

using namespace std;

/// Tableaux triés
void afficherTT(vectPersonne tab, int nb)
{
    for (int k = 0; k < nb; ++k)
    {
        cout << tab[k].nom << ' ' << tab[k].prenom << ' ' << tab[k].num << endl;
    }
}


void ajouterTT(vectPersonne tab, int& nb, Personne p)
{
    int k = 0;

    // On cherche la bonne place
    while (comparerPersonne(tab[k], p) && k < nb)
    {
        ++k;
    }

    // Test personne déjà présente
    if (egalitePersonne(tab[k], p) && k < nb)
    {
        return;
    }

    // Décalage des éléments suivants
    for (int i = nb - 1; i >= k; --i)
    {
        tab[i+1] = tab[i];
    }

    // Remplissage de la bonne case
    tab[k] = p;

    // Incrémentation taille
    nb = nb + 1;
}

bool rechercherTT(vectPersonne tab, int nb, Personne p)
{
    int i = 0;

    while (!egalitePersonne(tab[i], p) && i < nb)
    {
        ++i;
    }

    return egalitePersonne(tab[i], p);
}

void supprimerTT(vectPersonne tab, int& nb, Personne p)
{
    int i = 0;
    while (!egalitePersonne(tab[i], p) && i < nb)
    {
        ++i;
    }

    if (i < nb)
    {
        for (int k = i; k < nb; ++k)
        {
            tab[k] = tab [k+1];
        }

        --nb;
    }
}

void lectureRepertoireTT(vectPersonne tab, int& nb)
{
    nb = 0;
    Personne g;
    ifstream monFlux("repertoire.txt");

    for (int k = 0; k < 10000; ++k)
    {
        monFlux >> g.nom >> g.prenom >> g.num;
        ajouterTT(tab, nb, g);
    }

}

/// Listes triées
void afficherLT(ElementListe* maListe)
{
    // Cas de base
    if (maListe == nullptr)
    {
        return;
    }

    // Affichage
    cout << maListe->valeur.nom << ' ' << maListe->valeur.prenom << ' ' << maListe->valeur.num << endl;

    // Appel récursif
    afficherLT(maListe->suivant);
}
///

ElementListe* ajouterLT(ElementListe* maListe, Personne p)
{
    // Cas liste vide DONC insertion
    if (maListe == nullptr)
    {
        ElementListe* rep = new ElementListe;

        rep->valeur = p;
        rep->precedent = nullptr;
        rep->suivant = nullptr;

        return rep;
    }

    // Cas d'égalité
    if (egalitePersonne(maListe->valeur, p))
    {
        return maListe;
    }

    // Cas bout de liste et besoin d'ajouter après DONC insertion
    if (maListe->suivant == nullptr && comparerPersonne(maListe->valeur, p))
    {
        ElementListe* nouv = new ElementListe;

        nouv->valeur = p;
        nouv->precedent = maListe;
        nouv->suivant = nullptr;

        maListe->suivant = nouv;

        return maListe;
    }

    // Cas bout de liste et besoin d'ajouter avant DONC insertion
    if (comparerPersonne(p, maListe->valeur)/*maListe->suivant == nullptr*/) // On a forcément maListe->valeur > p
    {
        ElementListe* nouv = new ElementListe;

        nouv->valeur = p;
        nouv->precedent = nullptr;
        nouv->suivant = maListe;

        maListe->precedent = nouv;

        return nouv;
    }

    // Cas actuel inférieur et suivant supérieur DONC insertion
    if (comparerPersonne(maListe->valeur, p) && comparerPersonne(p, maListe->suivant->valeur))
    {
        ElementListe* nouv = new ElementListe;

        nouv->valeur = p;
        nouv->precedent = maListe;
        nouv->suivant = maListe->suivant;

        maListe->suivant = nouv;
        nouv->suivant->precedent = nouv;

        return maListe;
    }

    // Cas actuel inférieur et suivant inférieur DONC appel récursif
    ElementListe* rep = maListe;
    rep->suivant = ajouterLT(maListe->suivant, p);

    return rep;
}

bool rechercherLT(ElementListe* maListe, Personne p)
{
    // Cas où la liste est vide
    if (maListe == nullptr)
    {
        return false;
    }
    // Cas actuel égal donc recherche aboutit
    else if (egalitePersonne(maListe->valeur, p))
    {
        return true;
    }
    // Cas actuel différent DONC appel récursif
    else
    {
        rechercherLT(maListe->suivant);
    }
}

ElementListe* supprimerLT(ElementListe* maListe, Personne p)
{
	// Cas où la liste est vide
    if (maListe == nullptr)
    {
        return nullptr;
    }
    // Cas actuel est celui qu'on veut supprimer
    else if (egalitePersonne(maListe->valeur, p))
    {
		// Cas actuel n'est pas le premier de la liste
        if (maListe->precedent != nullptr)
            maListe->precedent->suivant = maListe->suivant;
            
		// Cas actuel n'est pas le dernier de la liste
        if (maListe->suivant != nullptr)
            maListe->suivant->precedent = maListe->precedent;

        return maListe->suivant;
    }
    // Cas actuel différent DONC appel récursif
    else
    {
        supprimerLT(maListe->suivant);
    }
}

ElementListe* lectureRepertoireLT(ifstream* flux, int iter)
{
    // En cas de démarrage
    if (flux == nullptr)
    {
        flux = new ifstream("repertoire.txt");
    }

    // Cas de base
    if (iter >= 10000)
        return nullptr;

    // Récursivité
    ElementListe* rep;
    rep->precedent = nullptr;
    (*flux) >> rep->valeur.nom >> rep->valeur.prenom >> rep->valeur.num;
    rep->suivant = lectureRepertoireLT(flux, iter++);

    // Raccrochage
    if (rep->suivant != nullptr)
    {
        rep->suivant->precedent = rep;
    }

    // Fin
    return rep;
}