#include "infinite_canvas/theme.h"

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

#if defined(PLATFORM_WEB) || defined(__EMSCRIPTEN__)
#include <emscripten/emscripten.h>

EM_JS(int, Canvas_Web_Prefers_Dark, (), {
    return window.matchMedia &&
        window.matchMedia("(prefers-color-scheme: dark)").matches ? 1 : 0;
});
#elif defined(_WIN32)
#include <windows.h>
#else
#include <stdio.h>
#endif

Canvas_Theme_Mode Canvas_Theme_Mode_From_String(const char *p_value)
{
    if (!p_value || strcmp(p_value, "auto") == 0) return CANVAS_THEME_AUTO;
    if (strcmp(p_value, "light") == 0) return CANVAS_THEME_LIGHT;
    if (strcmp(p_value, "dark") == 0) return CANVAS_THEME_DARK;
    return CANVAS_THEME_AUTO;
}

boolean Canvas_System_Prefers_Dark(void)
{
#if defined(PLATFORM_WEB) || defined(__EMSCRIPTEN__)
    return Canvas_Web_Prefers_Dark() ? TRUE : FALSE;
#elif defined(_WIN32)
    DWORD light_theme = 1;
    DWORD size = sizeof(light_theme);
    LSTATUS status = RegGetValueA(
        HKEY_CURRENT_USER,
        "Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
        "AppsUseLightTheme",
        RRF_RT_REG_DWORD,
        NULL,
        &light_theme,
        &size);
    return status == ERROR_SUCCESS && light_theme == 0 ? TRUE : FALSE;
#elif defined(__APPLE__)
    FILE *p_pipe = popen("defaults read -g AppleInterfaceStyle 2>/dev/null", "r");
    if (!p_pipe) return FALSE;
    char value[32] = {0};
    boolean dark = fgets(value, sizeof(value), p_pipe) &&
        strstr(value, "Dark") ? TRUE : FALSE;
    pclose(p_pipe);
    return dark;
#else
    const char *p_gtk_theme = getenv("GTK_THEME");
    if (p_gtk_theme &&
        (strstr(p_gtk_theme, "dark") || strstr(p_gtk_theme, "Dark"))) {
        return TRUE;
    }

    FILE *p_pipe = popen(
        "gsettings get org.gnome.desktop.interface color-scheme 2>/dev/null",
        "r");
    if (!p_pipe) return FALSE;
    char value[64] = {0};
    boolean dark = fgets(value, sizeof(value), p_pipe) &&
        strstr(value, "prefer-dark") ? TRUE : FALSE;
    pclose(p_pipe);
    return dark;
#endif
}

void Canvas_Theme_Resolve(Canvas_Theme *p_theme, Canvas_Theme_Mode mode)
{
    Canvas_Theme_Mode resolved = mode;
    if (resolved == CANVAS_THEME_AUTO) {
        resolved = Canvas_System_Prefers_Dark() ?
            CANVAS_THEME_DARK :
            CANVAS_THEME_LIGHT;
    }

    *p_theme = (Canvas_Theme){
        .requested_mode = mode,
        .resolved_mode = resolved,
    };
    if (resolved == CANVAS_THEME_DARK) {
        p_theme->background = (Color){15, 15, 17, 255};
        p_theme->surface = (Color){24, 24, 27, 255};
        p_theme->surface_muted = (Color){39, 39, 42, 255};
        p_theme->border = (Color){63, 63, 70, 255};
        p_theme->text = (Color){244, 244, 245, 255};
        p_theme->text_muted = (Color){161, 161, 170, 255};
        p_theme->accent = (Color){167, 139, 250, 255};
        p_theme->accent_soft = (Color){46, 35, 72, 255};
        p_theme->on_accent = (Color){255, 255, 255, 255};
        p_theme->selection = (Color){196, 181, 253, 230};
        p_theme->entity_outline = (Color){255, 255, 255, 26};
        p_theme->button = (Color){63, 63, 70, 255};
        p_theme->button_hover = (Color){82, 82, 91, 255};
        p_theme->button_active = (Color){124, 58, 237, 255};
        p_theme->button_active_hover = (Color){139, 92, 246, 255};
        p_theme->switch_track_off = (Color){63, 63, 70, 255};
        p_theme->switch_track_off_hover = (Color){82, 82, 91, 255};
        p_theme->switch_track_on = (Color){52, 211, 153, 255};
        p_theme->switch_track_on_hover = (Color){110, 231, 183, 255};
        p_theme->switch_thumb = (Color){250, 250, 250, 255};
        p_theme->pin = (Color){251, 191, 36, 255};
        p_theme->danger = (Color){248, 113, 113, 255};
        p_theme->shadow = (Color){0, 0, 0, 110};
        p_theme->toast_surface = (Color){24, 24, 27, 255};
        p_theme->toast_border = (Color){63, 63, 70, 255};
    } else {
        p_theme->background = (Color){255, 255, 255, 255};
        p_theme->surface = (Color){255, 255, 255, 252};
        p_theme->surface_muted = (Color){244, 247, 251, 255};
        p_theme->border = (Color){205, 211, 221, 255};
        p_theme->text = (Color){24, 24, 27, 255};
        p_theme->text_muted = (Color){113, 113, 122, 255};
        p_theme->accent = (Color){37, 99, 235, 255};
        p_theme->accent_soft = (Color){239, 246, 255, 255};
        p_theme->on_accent = (Color){255, 255, 255, 255};
        p_theme->selection = (Color){0, 122, 255, 230};
        p_theme->entity_outline = (Color){0, 0, 0, 20};
        p_theme->button = (Color){24, 24, 27, 255};
        p_theme->button_hover = (Color){39, 39, 42, 255};
        p_theme->button_active = (Color){37, 99, 235, 255};
        p_theme->button_active_hover = (Color){59, 130, 246, 255};
        p_theme->switch_track_off = (Color){205, 211, 221, 255};
        p_theme->switch_track_off_hover = (Color){161, 161, 170, 255};
        p_theme->switch_track_on = (Color){22, 163, 74, 255};
        p_theme->switch_track_on_hover = (Color){34, 197, 94, 255};
        p_theme->switch_thumb = (Color){255, 255, 255, 255};
        p_theme->pin = (Color){217, 119, 6, 255};
        p_theme->danger = (Color){220, 38, 38, 255};
        p_theme->shadow = (Color){15, 23, 42, 36};
        p_theme->toast_surface = (Color){255, 255, 255, 255};
        p_theme->toast_border = (Color){212, 216, 223, 255};
    }
}

void Canvas_Theme_Toggle(Canvas_Theme *p_theme)
{
    Canvas_Theme_Resolve(
        p_theme,
        p_theme->resolved_mode == CANVAS_THEME_DARK ?
            CANVAS_THEME_LIGHT :
            CANVAS_THEME_DARK);
}

void Canvas_Theme_Draw_Shadow(
    const Canvas_Theme *p_theme,
    Rectangle bounds,
    float roundness,
    int32 segments,
    float zoom,
    float opacity)
{
    float offset = 6.0f / zoom;
    float shadow_alpha = ((float)p_theme->shadow.a / 255.0f) * opacity;
    DrawRectangleRounded(
        (Rectangle){
            bounds.x + offset,
            bounds.y + offset,
            bounds.width,
            bounds.height,
        },
        roundness,
        segments,
        Fade(p_theme->shadow, shadow_alpha));
}
