// config.c — Global program configuration (config.ini next to binary)

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

#ifdef __APPLE__
#include <unistd.h>
#include <libgen.h>
#include <mach-o/dyld.h>
#else
#include <windows.h>
#endif

Config g_config = {0};

////////////////////////////////
// Path resolution

static void config_get_path(char *out, S32 out_size) {
    char exe_path[CONFIG_PATH_MAX];
#ifdef __APPLE__
    U32 sz = sizeof(exe_path);
    _NSGetExecutablePath(exe_path, &sz);
#else
    GetModuleFileNameA(NULL, exe_path, CONFIG_PATH_MAX);
#endif
    // Strip binary name to get directory
    char *sep = strrchr(exe_path, '/');
#ifndef __APPLE__
    char *bsep = strrchr(exe_path, '\\');
    if (bsep && (!sep || bsep > sep)) sep = bsep;
#endif
    if (sep) sep[1] = '\0';
    snprintf(out, out_size, "%sconfig.ini", exe_path);
}

////////////////////////////////
// Helpers

static void config_trim(char *s) {
    char *start = s;
    while (*start == ' ' || *start == '\t') start++;
    if (start != s) memmove(s, start, strlen(start) + 1);
    S32 len = (S32)strlen(s);
    while (len > 0 && (s[len - 1] == ' ' || s[len - 1] == '\t' ||
                       s[len - 1] == '\r' || s[len - 1] == '\n'))
        s[--len] = '\0';
}

////////////////////////////////
// Defaults

static void config_set_defaults(void) {
    MemoryZeroStruct(&g_config);
    snprintf(g_config.theme, sizeof(g_config.theme), "%s", "Gruvbox Dark");
    g_config.show_line_numbers = 1;
    g_config.syntax_enabled = 1;
    g_config.block_cursor = 1;
    g_config.cursor_smear = 1;
    g_config.smooth_scroll = 1;
    g_config.ui_scale = 1.0f;
    g_config.editor_font_size = 15.0f;
    snprintf(g_config.editor_font, sizeof(g_config.editor_font), "%s", "FiraCode");
    snprintf(g_config.ui_font, sizeof(g_config.ui_font), "%s", "Inter");
    g_config.window_width = 1280;
    g_config.window_height = 800;
    g_config.active_project[0] = '\0';
    g_config.recent_dir_count = 0;
}

////////////////////////////////
// Load

static void config_load(void) {
    config_set_defaults();

    char path[CONFIG_PATH_MAX];
    config_get_path(path, sizeof(path));

    FILE *f = fopen(path, "rb");
    if (!f) {
        // No config file — write defaults
        config_save();
        return;
    }

    char line_buf[CONFIG_PATH_MAX + 64];
    char current_section[64] = {0};

    while (fgets(line_buf, sizeof(line_buf), f)) {
        config_trim(line_buf);
        if (line_buf[0] == '\0' || line_buf[0] == '#' || line_buf[0] == ';')
            continue;

        // Section header
        if (line_buf[0] == '[') {
            char *close = strchr(line_buf, ']');
            if (close) {
                *close = '\0';
                snprintf(current_section, sizeof(current_section), "%s", line_buf + 1);
            }
            continue;
        }

        // Key = value
        char *eq = strchr(line_buf, '=');
        if (!eq) continue;
        *eq = '\0';
        char *key = line_buf;
        char *val = eq + 1;
        config_trim(key);
        config_trim(val);

        if (strcmp(current_section, "general") == 0) {
            if (strcmp(key, "theme") == 0)
                snprintf(g_config.theme, sizeof(g_config.theme), "%s", val);
            else if (strcmp(key, "show_line_numbers") == 0)
                g_config.show_line_numbers = (strcmp(val, "true") == 0);
            else if (strcmp(key, "syntax_enabled") == 0)
                g_config.syntax_enabled = (strcmp(val, "true") == 0);
            else if (strcmp(key, "block_cursor") == 0)
                g_config.block_cursor = (strcmp(val, "true") == 0);
            else if (strcmp(key, "cursor_smear") == 0)
                g_config.cursor_smear = (strcmp(val, "true") == 0);
            else if (strcmp(key, "smooth_scroll") == 0)
                g_config.smooth_scroll = (strcmp(val, "true") == 0);
            else if (strcmp(key, "ui_scale") == 0)
                g_config.ui_scale = (F32)atof(val);
            else if (strcmp(key, "editor_font_size") == 0)
                g_config.editor_font_size = (F32)atof(val);
            else if (strcmp(key, "editor_font") == 0)
                snprintf(g_config.editor_font, sizeof(g_config.editor_font), "%s", val);
            else if (strcmp(key, "ui_font") == 0)
                snprintf(g_config.ui_font, sizeof(g_config.ui_font), "%s", val);
            else if (strcmp(key, "active_project") == 0)
                snprintf(g_config.active_project, sizeof(g_config.active_project), "%s", val);
            else if (strcmp(key, "window_width") == 0)
                g_config.window_width = atoi(val);
            else if (strcmp(key, "window_height") == 0)
                g_config.window_height = atoi(val);
        } else if (strcmp(current_section, "recent_dirs") == 0) {
            // Keys are "0", "1", "2", etc.
            S32 idx = atoi(key);
            if (idx >= 0 && idx < CONFIG_MAX_RECENT_DIRS && val[0] != '\0') {
                snprintf(g_config.recent_dirs[idx], CONFIG_PATH_MAX, "%s", val);
                if (idx + 1 > g_config.recent_dir_count)
                    g_config.recent_dir_count = idx + 1;
            }
        }
    }

    fclose(f);
}

////////////////////////////////
// Save

static void config_save(void) {
    char path[CONFIG_PATH_MAX];
    config_get_path(path, sizeof(path));

    FILE *f = fopen(path, "wb");
    if (!f) return;

    fprintf(f, "# codeMAX configuration — managed by the program\r\n\r\n");

    fprintf(f, "[general]\r\n");
    fprintf(f, "theme = %s\r\n", g_config.theme);
    fprintf(f, "show_line_numbers = %s\r\n", g_config.show_line_numbers ? "true" : "false");
    fprintf(f, "syntax_enabled = %s\r\n", g_config.syntax_enabled ? "true" : "false");
    fprintf(f, "block_cursor = %s\r\n", g_config.block_cursor ? "true" : "false");
    fprintf(f, "cursor_smear = %s\r\n", g_config.cursor_smear ? "true" : "false");
    fprintf(f, "smooth_scroll = %s\r\n", g_config.smooth_scroll ? "true" : "false");
    fprintf(f, "ui_scale = %.2f\r\n", g_config.ui_scale);
    fprintf(f, "editor_font_size = %.1f\r\n", g_config.editor_font_size);
    fprintf(f, "editor_font = %s\r\n", g_config.editor_font);
    fprintf(f, "ui_font = %s\r\n", g_config.ui_font);
    fprintf(f, "window_width = %d\r\n", g_config.window_width);
    fprintf(f, "window_height = %d\r\n", g_config.window_height);
    if (g_config.active_project[0] != '\0')
        fprintf(f, "active_project = %s\r\n", g_config.active_project);

    fprintf(f, "\r\n[recent_dirs]\r\n");
    for (S32 i = 0; i < g_config.recent_dir_count; i++) {
        if (g_config.recent_dirs[i][0] != '\0')
            fprintf(f, "%d = %s\r\n", i, g_config.recent_dirs[i]);
    }

    fclose(f);
}

////////////////////////////////
// Recent directories

static void config_push_recent_dir(const char *dir) {
    if (!dir || dir[0] == '\0') return;

    // Normalize path for comparison
    char norm[CONFIG_PATH_MAX];
    snprintf(norm, sizeof(norm), "%s", dir);
    for (char *p = norm; *p; p++) {
        if (*p == '/') *p = '\\';
    }

    // Check if already in list — if so, move to front
    S32 existing = -1;
    for (S32 i = 0; i < g_config.recent_dir_count; i++) {
#ifdef __APPLE__
        if (strcmp(g_config.recent_dirs[i], norm) == 0) { existing = i; break; }
#else
        if (_stricmp(g_config.recent_dirs[i], norm) == 0) { existing = i; break; }
#endif
    }

    if (existing == 0) return; // already at front

    // Save the entry if it exists, or use the new dir
    char entry[CONFIG_PATH_MAX];
    snprintf(entry, sizeof(entry), "%s", norm);

    // Shift entries down
    S32 start = (existing >= 0) ? existing : g_config.recent_dir_count;
    if (start >= CONFIG_MAX_RECENT_DIRS) start = CONFIG_MAX_RECENT_DIRS - 1;
    for (S32 i = start; i > 0; i--)
        memcpy(g_config.recent_dirs[i], g_config.recent_dirs[i - 1], CONFIG_PATH_MAX);

    // Insert at front
    snprintf(g_config.recent_dirs[0], CONFIG_PATH_MAX, "%s", entry);

    if (existing < 0 && g_config.recent_dir_count < CONFIG_MAX_RECENT_DIRS)
        g_config.recent_dir_count++;

    config_save();
}
