#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "cell.h"

int plugin_algo_carre_riviere(unsigned long total_cellules,
                              unsigned long total_liens,
                              cell * tabcell,
                              char *params,
                              char *buffer_erreur, int maxlen_erreur)
{
    cell_list *chemin = NULL;
    cell_list *chemin_tmp;
    cell *cell_tmp;
    int nb_liens_restants;
    int i, j;
    int ret = 0;

    if (params) {
        snprintf(buffer_erreur, maxlen_erreur,
                 "Il ne faut aucun paramètre pour ce type d'algorithme\n");
        return -1;
    }

    /* première alloc */
    chemin = (cell_list *) calloc(1, sizeof(cell_list));

    /* tirer première cellule au hasard */
    chemin->curr = &tabcell[rand() % total_cellules];

    nb_liens_restants = total_liens;
    while (nb_liens_restants) {
        /* chercher à joindre une cellule pas encore jointe */
        do {
            if (chemin->curr->nb_links == 0) {
                chemin_tmp = chemin->prev;
                free(chemin);
                chemin = chemin_tmp;
                if (chemin == NULL) {
                    snprintf(buffer_erreur, maxlen_erreur,
                             "??? n'importe quoi\n");
                    ret = -1;
                    goto plugin_algo_carre_riviere_fin;
                }
                chemin->next = NULL;
                fflush(NULL);
                i = -1;
                break;
            }
            i = rand() % chemin->curr->nb_links;
            cell_tmp = chemin->curr->links[i].link;
            if (cell_tmp->tag > 0) {
                /* cellule à joindre déjà faite => mettre mur */
                cell_deplacer_link_vers_walls(chemin->curr, i);

                /* rechercher le lien opposé de l'autre côté */
                for (j = 0; j < cell_tmp->nb_links; j++) {
                    if (cell_tmp->links[j].link == chemin->curr)
                        break;
                }
                if (j == cell_tmp->nb_links) {
                    snprintf(buffer_erreur, maxlen_erreur,
                             "Erreur de recherche de cellule, pas normal\n");
                    ret = -1;
                    goto plugin_algo_carre_riviere_fin;
                }

                cell_deplacer_link_vers_walls(cell_tmp, j);

                nb_liens_restants -= 2;
                if (nb_liens_restants == 0)
                    break;
            }
        } while (cell_tmp->tag > 0);

        /* si on a fait que des murs, il peut ne plus y avoir de liens : */
        if (nb_liens_restants == 0)
            break;

        /* si on est remonté dans le chemin => boucler : */
        if (i == -1)
            continue;

        /* marquer la courante comme faite */
        chemin->curr->tag++;

        /* déplacer le lien dans paths */
        cell_deplacer_link_vers_paths(chemin->curr, i);

        /* ajouter une nouvelle à la liste */
        chemin_tmp = (cell_list *) calloc(1, sizeof(cell_list));

        /* suivante = case choisie */
        chemin_tmp->curr = cell_tmp;
        chemin_tmp->prev = chemin;
        chemin->next = chemin_tmp;

        /* rechercher le lien opposé de l'autre côté */
        for (i = 0; i < cell_tmp->nb_links; i++) {
            if (cell_tmp->links[i].link == chemin->curr)
                break;
        }
        if (i == cell_tmp->nb_links) {
            snprintf(buffer_erreur, maxlen_erreur,
                     "Erreur de recherche de cellule, pas normal\n");
            ret = -1;
            goto plugin_algo_carre_riviere_fin;
        }

        cell_deplacer_link_vers_paths(cell_tmp, i);

        /* on vient de déplacer deux liens */
        nb_liens_restants -= 2;

        /* la courante devient celle allouée */
        chemin = chemin_tmp;
    }
  plugin_algo_carre_riviere_fin:
    do {
        chemin_tmp = chemin->prev;
        free(chemin);
        chemin = chemin_tmp;
    } while (chemin);
    return ret;
}
