#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

typedef struct File {
    unsigned char* data;
    int len;
} File;

int file_exist(const char* filename) {
    return access(filename, F_OK) == 0;
}

File read_entire_file(const char* filename)
{
    FILE *f = fopen(filename, "r");
    fseek(f, 0, SEEK_END);
    long fsize = ftell(f);
    fseek(f, 0, SEEK_SET);

    unsigned char *string = malloc(fsize);
    fread(string, fsize, 1, f);
    fclose(f);

    return (File) {
        .len = fsize,
        .data = string,
    };
}

void file_free(File file)
{
    free(file.data);
}

void write_entire_file(const char* filename, File file)
{
    FILE *f = fopen(filename, "w");
    fwrite(file.data, file.len, 1, f);
    fclose(f);
}

// TODO: str -> format, ... | vsnprintf
int file_append(File file, int at, const char* format, ...)
{
    int len = strlen(format);
    memcpy(&file.data[at], format, len);
    return len;
}

int main(int argc, const char *argv[])
{
    if (argc != 4) {
        printf("ERR: missing argument.\n");
        printf("usage: %s <input asset> <output header file> <variable name>\n", argv[0]);
        return 1;
    }

    const char *input = argv[1];
    const char *output = argv[2];
    const char *name = argv[3];

    if (!file_exist(input)) {
        printf("ERR: input file '%s' do not exist.\n", input);
        return 1;
    }

    File asset = read_entire_file(input);

    File header;
    header.len = asset.len*6 /*0xFF, */ + asset.len/20*5 /*\n    */ + 200 /*header+footer+banane*/ + strlen(name)*2;
    header.data = malloc(header.len);
    int cursor = 0;

    // TODO: refacto ce truc de con la
    // cursor += file_append(header, cursor, "static const int %s_size = %d;\n", name, asset.len);
    cursor += snprintf((char*)header.data+cursor, header.len-cursor, "static const int %s_size = %d;\n", name, asset.len);
    cursor += snprintf((char*)header.data+cursor, header.len-cursor, "static const unsigned char %s_data[%d] = {", name, asset.len);

    int i;
    for (i = 0; i < asset.len; i++) {
        if (!(i%20)) cursor += snprintf((char*)header.data+cursor, header.len-cursor, "\n    ");
        cursor += snprintf((char*)header.data+cursor, header.len-cursor, "0x%02X, ", asset.data[i]);
    }

    cursor += snprintf((char*)header.data+cursor, header.len-cursor, "\n};\n");

    header.len = cursor;
    write_entire_file(output, header);

    return 0;
}
