#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#include <direct.h>
#define getcwd _getcwd
#else
#include <unistd.h>
#endif

#include "../src/interface/katconfig.h"
#include "../src/interface/logger.h"
#include "../src/interface/util.h"

static int failure = 0;
extern t_config config;

static void output_result(int result, const char *test, const char *value,
        const char *error)
{
    if (result) {
        printf("[PASS] %s Result=%s\n", test, value);
    }
    else {
        ++failure;
        printf("[FAIL] %s %s Result=%s\n", test, error, value);
    }
}

static void make_dir(const char *path)
{
    util_mkdir(path, UTIL_DEFAULT_DIR_MODE);
}

static void make_file(const char *path)
{
    FILE *fp = fopen(path, "wb");

    if (fp) {
        fputc(0, fp);
        fclose(fp);
    }
}

static void set_path(char **target, const char *value)
{
    util_alloc_string(target, value ? value : "");
}

static void check_start_dir(const char *test, const char *expected)
{
    char *actual = config_alloc_rom_browser_start_dir();

    if (!expected) {
        output_result(actual == NULL, test, actual ? actual : "NULL",
                "Expected NULL");
    }
    else if (actual && !strcmp(actual, expected)) {
        output_result(1, test, actual, "");
    }
    else {
        char error[KAT_PATH_MAX + 64];
        snprintf(error, sizeof(error), "Expected %s", expected);
        output_result(0, test, actual ? actual : "NULL", error);
    }

    free(actual);
}

int main(void)
{
    char cwd[KAT_PATH_MAX];
    char root[KAT_PATH_MAX];
    char program_dir[KAT_PATH_MAX];
    char last_dir[KAT_PATH_MAX];
    char last_file_rel[KAT_PATH_MAX];
    char rom_dir[KAT_PATH_MAX];
    char bios_dir[KAT_PATH_MAX];
    char bios_file[KAT_PATH_MAX];
    char sep;
    char *testv[] = { "test_rom_browser_start_dir" };

    logger_init();
    config_init(1, testv);

    sep = util_get_dir_seperator_character();
    getcwd(cwd, sizeof(cwd));

    snprintf(root, sizeof(root), "%s%crom_browser_start_dir_case", cwd, sep);
    snprintf(program_dir, sizeof(program_dir), "%s%cprogram", root, sep);
    snprintf(last_dir, sizeof(last_dir), "%s%clast", root, sep);
    snprintf(rom_dir, sizeof(rom_dir), "%s%cconfigured_roms", program_dir, sep);
    snprintf(bios_dir, sizeof(bios_dir), "%s%cdownload", program_dir, sep);
    snprintf(bios_file, sizeof(bios_file), "%s%cbios.bin", bios_dir, sep);
    snprintf(last_file_rel, sizeof(last_file_rel),
            "rom_browser_start_dir_case%clast%cgame.rom", sep, sep);

    make_dir(root);
    make_dir(program_dir);
    make_dir(last_dir);
    make_dir(rom_dir);
    make_dir(bios_dir);
    make_file(bios_file);

    util_set_program_path(program_dir);

    set_path(&config.general.rom, last_file_rel);
    set_path(&config.machine.rom_dir, "configured_roms");
    set_path(&config.machine.bios, "download/bios.bin");
    check_start_dir("ROM Browser Start - Last ROM Parent", last_dir);

    set_path(&config.general.rom, "");
    set_path(&config.machine.rom_dir, "configured_roms");
    set_path(&config.machine.bios, "download/bios.bin");
    check_start_dir("ROM Browser Start - ROM Dir", rom_dir);

    set_path(&config.general.rom, "");
    set_path(&config.machine.rom_dir, "roms");
    set_path(&config.machine.bios, "download/bios.bin");
    check_start_dir("ROM Browser Start - BIOS Dir", bios_dir);

    set_path(&config.general.rom, "");
    set_path(&config.machine.rom_dir, "missing_roms");
    set_path(&config.machine.bios, "5200.bin");
    check_start_dir("ROM Browser Start - Current Dir Fallback", NULL);

    config_exit();
    logger_exit();

    return failure;
}
