#include "common.h"
#include "buffer.h"

#include <stdio.h>

WriteBuffer createWriteBuffer(FILE* file) {
    WriteBuffer buffer = {
        .dest_file = file
    };

    return buffer;
}

void putBuffer(char bit, WriteBuffer* buffer) {
    // Si le tampon déborde, écriture dans le fichier
    if (buffer->pending_bits == 8) {
        flushBuffer(buffer);
    }

    // Décalage et insertion du bit donné
    buffer->data <<= 1;
    buffer->data |= bit;
    buffer->pending_bits += 1;
}

void flushBuffer(WriteBuffer* buffer) {
    // FIXME: gérer les erreurs d'écriture

    if (buffer->pending_bits) {
        // Alignement des données à gauche de l'octet (si l'octet n'est pas
        // complet, il sera aligné par des '0' à droite)
        buffer->data <<= 8 - buffer->pending_bits;
        fputc(buffer->data, buffer->dest_file);

        buffer->data = 0;
        buffer->pending_bits = 0;
        buffer->flushed_count++;
    }
}

bytecount getFlushedCount(WriteBuffer* buffer) {
    return buffer->flushed_count;
}

ReadBuffer createReadBuffer(FILE* file) {
    ReadBuffer buffer = {
        .data = fgetc(file),
        .next_bit = 7,
        .source_file = file
    };

    return buffer;
}

char getBuffer(ReadBuffer* buffer) {
    if (feof(buffer->source_file)) {
        return -1;
    }

    // Lecture du n-ième bit dans le dernier octet lu
    char result = (
        buffer->data &
        (1 << buffer->next_bit)
    ) != 0;

    if (buffer->next_bit > 0) {
        // Il reste des bits à lire, décalage du compteur
        buffer->next_bit--;
    } else {
        // Besoin de lire le prochain octet depuis le fichier
        buffer->data = fgetc(buffer->source_file);
        buffer->next_bit = 7;
    }

    return result;
}
