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

// files.c corrections : MSB-first within each byte

bit_array file_to_bits(const char *filename) {
    bit_array arr = {0};

    FILE *f = fopen(filename, "rb");
    if (!f) {
        perror("fopen");
        return arr;
    }

    fseek(f, 0, SEEK_END);
    long file_size = ftell(f);
    rewind(f);

    if (file_size <= 0) {
        fclose(f);
        return arr;
    }

    uint8_t *raw = (uint8_t*)malloc(file_size);
    if (!raw) { fclose(f); return arr; }
    fread(raw, 1, file_size, f);
    fclose(f);

    arr.nb_bits = (size_t)file_size * 8;
    arr.bits = (uint8_t*)malloc(arr.nb_bits * sizeof(uint8_t));
    if (!arr.bits) { free(raw); arr.nb_bits = 0; return arr; }

    // MSB-first in each byte: bit 7 -> index 0, bit 0 -> index 7
    for (size_t i = 0; i < (size_t)file_size; i++) {
        for (int b = 0; b < 8; b++) {
            arr.bits[i * 8 + b] = (raw[i] >> (7 - b)) & 1u;
        }
    }

    free(raw);
    return arr;
}

int bits_to_file(const char *filename, const bit_array *arr) {
    if (!arr || !arr->bits) return -1;

    size_t nb_bytes = (arr->nb_bits + 7) / 8;
    uint8_t *raw = (uint8_t*)calloc(nb_bytes, 1);
    if (!raw) return -1;

    // MSB-first packing: index bit 0 -> place at position 7 of first byte
    for (size_t i = 0; i < arr->nb_bits; i++) {
        if (arr->bits[i]) {
            size_t byte_idx = i / 8;
            int bit_in_byte = i % 8; // 0..7
            raw[byte_idx] |= (1u << (7 - bit_in_byte));
        }
    }

    FILE *f = fopen(filename, "wb");
    if (!f) { perror("fopen"); free(raw); return -1; }
    fwrite(raw, 1, nb_bytes, f);
    fclose(f);
    free(raw);
    return 0;
}

// Génère un nom du type "output.<ext>" où <ext> est l'extension du fichier d'entrée
char* make_output_filename(const char *input_filename) {
    const char *dot = strrchr(input_filename, '.');
    const char *ext = dot ? dot + 1 : "bin";

    // Construire "output.<ext>"
    size_t len = strlen(ext) + strlen("output.") + 1;
    char *out = (char*)malloc(len);
    if (!out) return NULL;

    snprintf(out, len, "output.%s", ext);
    return out;
}


// Libérer la mémoire
void free_bit_array(bit_array *arr) {
    if (arr && arr->bits) {
        free(arr->bits);
        arr->bits = NULL;
        arr->nb_bits = 0;
    }
}

