#include "plot_theme.h"

// ---------------------------------------------------------------------------
// Preset structs
// ---------------------------------------------------------------------------

PlotTheme plot_theme_preset_dark() {
    PlotTheme t;
    t.name          = "dark";
    t.bg            = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
    t.frame_bg      = ImVec4(0.14f, 0.14f, 0.17f, 1.00f);
    t.text          = ImVec4(0.88f, 0.88f, 0.90f, 1.00f);
    t.grid          = ImVec4(0.30f, 0.30f, 0.35f, 0.60f);
    t.palette_count = 10;
    t.palette[0]    = ImVec4(0.33f, 0.62f, 0.91f, 1.00f); // steel blue
    t.palette[1]    = ImVec4(0.35f, 0.78f, 0.54f, 1.00f); // soft green
    t.palette[2]    = ImVec4(0.96f, 0.60f, 0.25f, 1.00f); // warm orange
    t.palette[3]    = ImVec4(0.85f, 0.38f, 0.42f, 1.00f); // muted red
    t.palette[4]    = ImVec4(0.72f, 0.52f, 0.88f, 1.00f); // lavender
    t.palette[5]    = ImVec4(0.38f, 0.80f, 0.82f, 1.00f); // teal
    t.palette[6]    = ImVec4(0.95f, 0.80f, 0.32f, 1.00f); // gold
    t.palette[7]    = ImVec4(0.60f, 0.82f, 0.38f, 1.00f); // lime
    t.palette[8]    = ImVec4(0.90f, 0.55f, 0.75f, 1.00f); // pink
    t.palette[9]    = ImVec4(0.55f, 0.70f, 0.95f, 1.00f); // periwinkle
    return t;
}

PlotTheme plot_theme_preset_light() {
    PlotTheme t;
    t.name          = "light";
    t.bg            = ImVec4(0.97f, 0.97f, 0.97f, 1.00f);
    t.frame_bg      = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
    t.text          = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
    t.grid          = ImVec4(0.70f, 0.70f, 0.72f, 0.60f);
    t.palette_count = 10;
    t.palette[0]    = ImVec4(0.12f, 0.47f, 0.71f, 1.00f); // deep blue
    t.palette[1]    = ImVec4(0.17f, 0.63f, 0.17f, 1.00f); // deep green
    t.palette[2]    = ImVec4(0.84f, 0.37f, 0.00f, 1.00f); // burnt orange
    t.palette[3]    = ImVec4(0.84f, 0.15f, 0.16f, 1.00f); // vivid red
    t.palette[4]    = ImVec4(0.58f, 0.40f, 0.74f, 1.00f); // purple
    t.palette[5]    = ImVec4(0.09f, 0.75f, 0.81f, 1.00f); // cyan
    t.palette[6]    = ImVec4(0.74f, 0.74f, 0.13f, 1.00f); // olive
    t.palette[7]    = ImVec4(0.09f, 0.75f, 0.81f, 1.00f); // sky blue
    t.palette[8]    = ImVec4(0.89f, 0.47f, 0.76f, 1.00f); // rose
    t.palette[9]    = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); // grey
    return t;
}

PlotTheme plot_theme_preset_high_contrast() {
    PlotTheme t;
    t.name          = "high_contrast";
    t.bg            = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
    t.frame_bg      = ImVec4(0.05f, 0.05f, 0.05f, 1.00f);
    t.text          = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
    t.grid          = ImVec4(0.30f, 0.30f, 0.30f, 0.80f);
    t.palette_count = 10;
    t.palette[0]    = ImVec4(0.00f, 1.00f, 1.00f, 1.00f); // cyan neon
    t.palette[1]    = ImVec4(0.00f, 1.00f, 0.00f, 1.00f); // green neon
    t.palette[2]    = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); // orange neon
    t.palette[3]    = ImVec4(1.00f, 0.00f, 0.50f, 1.00f); // magenta
    t.palette[4]    = ImVec4(1.00f, 1.00f, 0.00f, 1.00f); // yellow
    t.palette[5]    = ImVec4(0.40f, 0.80f, 1.00f, 1.00f); // sky blue
    t.palette[6]    = ImVec4(1.00f, 0.40f, 0.40f, 1.00f); // salmon
    t.palette[7]    = ImVec4(0.60f, 1.00f, 0.40f, 1.00f); // lime
    t.palette[8]    = ImVec4(1.00f, 0.80f, 1.00f, 1.00f); // lavender bright
    t.palette[9]    = ImVec4(0.80f, 1.00f, 0.80f, 1.00f); // mint bright
    return t;
}

// ---------------------------------------------------------------------------
// Internal helper
// ---------------------------------------------------------------------------

static void apply_imgui_colors(const PlotTheme& theme) {
    ImGuiStyle& s = ImGui::GetStyle();
    s.Colors[ImGuiCol_WindowBg]       = theme.bg;
    s.Colors[ImGuiCol_ChildBg]        = theme.bg;
    s.Colors[ImGuiCol_PopupBg]        = theme.frame_bg;
    s.Colors[ImGuiCol_FrameBg]        = theme.frame_bg;
    s.Colors[ImGuiCol_FrameBgHovered] = theme.frame_bg;
    s.Colors[ImGuiCol_FrameBgActive]  = theme.frame_bg;
    s.Colors[ImGuiCol_Text]           = theme.text;
    s.Colors[ImGuiCol_TextDisabled]   = ImVec4(theme.text.x * 0.5f,
                                               theme.text.y * 0.5f,
                                               theme.text.z * 0.5f,
                                               0.80f);
}

static void apply_implot_colors(const PlotTheme& theme) {
    ImPlotStyle& ps = ImPlot::GetStyle();
    ps.Colors[ImPlotCol_PlotBg]       = theme.bg;
    ps.Colors[ImPlotCol_PlotBorder]   = theme.frame_bg;
    ps.Colors[ImPlotCol_FrameBg]      = theme.frame_bg;
    ps.Colors[ImPlotCol_LegendBg]     = theme.frame_bg;
    ps.Colors[ImPlotCol_LegendBorder] = theme.grid;
    ps.Colors[ImPlotCol_LegendText]   = theme.text;
    ps.Colors[ImPlotCol_TitleText]    = theme.text;
    ps.Colors[ImPlotCol_InlayText]    = theme.text;
    ps.Colors[ImPlotCol_AxisText]     = theme.text;
    ps.Colors[ImPlotCol_AxisGrid]     = theme.grid;
    ps.Colors[ImPlotCol_AxisTick]     = theme.grid;

    // Register custom colormap from palette
    const int count = theme.palette_count > 10 ? 10 : theme.palette_count;
    ImPlot::AddColormap(theme.name, theme.palette, count, false);
    ImPlot::SetColormap(theme.name);
}

// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------

void plot_theme_apply(const PlotTheme& theme) {
    apply_imgui_colors(theme);
    apply_implot_colors(theme);
}

void plot_theme_dark() {
    PlotTheme t = plot_theme_preset_dark();
    plot_theme_apply(t);
}

void plot_theme_light() {
    PlotTheme t = plot_theme_preset_light();
    plot_theme_apply(t);
}

void plot_theme_high_contrast() {
    PlotTheme t = plot_theme_preset_high_contrast();
    plot_theme_apply(t);
}
