// Paso 6: cuánto comprime cada archivo y cuánto tarda. Compilar con -O2 y sin sanitizers.
// Con --sizes solo imprime los tamaños, que no dependen de la máquina. Los tiempos sí dependen.
#include <cstring>
#include <exception>
#include <filesystem>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>

#include "bench.h"
#include "byte_file.h"
#include "huffman.h"

int main(int argc, char** argv) {
    bool sizes_only = argc > 1 && std::strcmp(argv[1], "--sizes") == 0;
    int first = sizes_only ? 2 : 1;
    if (argc <= first) {
        std::cerr << "uso: bench_compress [--sizes] archivo...\n";
        return 2;
    }
    std::cout << "archivo                original  comprimido       %";
    std::cout << (sizes_only ? "\n" : "   t.comp   t.desc\n");
    try {
        for (int i = first; i < argc; i++) {
            Bytes data = read_file(argv[i]);
            Bytes compressed = compress_bytes(data);
            if (decompress_bytes(compressed) != data) {
                std::cout << "no volvio igual: " << argv[i] << "\n";
                return 1;
            }
            std::string name = std::filesystem::path(argv[i]).filename().string();
            std::cout << std::left << std::setw(20) << name << std::right << std::setw(11) << data.size()
                      << std::setw(12) << compressed.size() << std::fixed << std::setprecision(1) << std::setw(8);
            if (data.empty()) {
                std::cout << "-";  // no se puede dividir entre 0
            } else {
                std::cout << 100.0 * double(compressed.size()) / double(data.size());
            }
            if (!sizes_only) {
                double compress_time = median_seconds(3, [&] { keep(compress_bytes(data).size()); });
                double decompress_time = median_seconds(3, [&] { keep(decompress_bytes(compressed).size()); });
                std::cout << std::setprecision(4) << std::setw(9) << compress_time << std::setw(9) << decompress_time;
            }
            std::cout << "\n";
        }
    } catch (const std::exception& error) {
        std::cerr << "bench_compress: " << error.what() << "\n";
        return 1;
    }
    return 0;
}
