#include "huftree.h"
#include "buffer.h"
#include "display.h"
#include "decompress.h"

#include <stdint.h>

void decompress(FILE* source, FILE* dest) {
    // ÉTAPE 1 : lecture du nombre de caractères originel. Cela permet
    // d'ignorer les bits d'alignement en fin de fichier
    uint64_t original_count = 0;
    fread(&original_count, sizeof(original_count), 1, source);
    printVerbose("Lecture du nombre de caractères : %d.\n", original_count);

    if (original_count == 0) {
        // Cas particulier : fichier vide, rien à restituer
        return;
    }

    // ÉTAPE 2 : reconstruction de l'arbre à partir des données linéarisées
    printVerbose("Reconstruction de l'arbre de Huffman.\n");
    ReadBuffer input = createReadBuffer(source);
    HufTree tree = readTree(&input);

    if (isVerbose()) {
        printTree(tree);
    }

    // ÉTAPE 3 : lecture des données compressées et interprétation grâce
    // à l'arbre de Huffman reconstitué
    printVerbose("\nLecture et interprétation des données compressées.\n");
    char next_bit = getBuffer(&input);
    uint64_t wrote_count = 0;

    while (next_bit != -1 && wrote_count < original_count) {
        HufTree current = tree;

        // Descente dans l'arbre, allant à gauche si un '0' est rencontré
        // ou à droite si un '1' est rencontré. Arrêt dès l'arrivée sur
        // une feuille
        while (
            next_bit != -1 &&
            current->child_l != NULL && current->child_r != NULL
        ) {
            if (next_bit == 0) {
                current = current->child_l;
            } else {
                current = current->child_r;
            }

            next_bit = getBuffer(&input);
        }

        // La valeur de la feuille trouvée est le caractère compressé :
        // on l'écrit dans le fichier
        fputc(current->value, dest);
        wrote_count++;
    }

    freeTree(tree);
}
