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

#define NK_INCLUDE_FIXED_TYPES
#define NK_INCLUDE_STANDARD_IO
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_INCLUDE_DEFAULT_ALLOCATOR
#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT
#define NK_INCLUDE_FONT_BAKING
#define NK_INCLUDE_DEFAULT_FONT

#include "nuklear.h"
#include "theme.h"

#define KAT_COLOR_MAP(NK_COLOR)\
    NK_COLOR(NK_COLOR_TEXT,                     175,175,175,255) \
    NK_COLOR(NK_COLOR_WINDOW,                   45, 45, 45, 255) \
    NK_COLOR(NK_COLOR_HEADER,                   40, 40, 40, 255) \
    NK_COLOR(NK_COLOR_BORDER,                   65, 65, 65, 255) \
    NK_COLOR(NK_COLOR_BUTTON,                   50, 50, 50, 255) \
    NK_COLOR(NK_COLOR_BUTTON_HOVER,             40, 40, 40, 255) \
    NK_COLOR(NK_COLOR_BUTTON_ACTIVE,            35, 35, 35, 255) \
    NK_COLOR(NK_COLOR_TOGGLE,                   100,100,100,255) \
    NK_COLOR(NK_COLOR_TOGGLE_HOVER,             120,120,120,255) \
    NK_COLOR(NK_COLOR_TOGGLE_CURSOR,            45, 45, 45, 255) \
    NK_COLOR(NK_COLOR_SELECT,                   45, 45, 45, 255) \
    NK_COLOR(NK_COLOR_SELECT_ACTIVE,            35, 35, 35,255)  \
    NK_COLOR(NK_COLOR_SLIDER,                   38, 38, 38, 255) \
    NK_COLOR(NK_COLOR_SLIDER_CURSOR,            100,100,100,255) \
    NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER,      120,120,120,255) \
    NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE,     150,150,150,255) \
    NK_COLOR(NK_COLOR_PROPERTY,                 38, 38, 38, 255) \
    NK_COLOR(NK_COLOR_EDIT,                     38, 38, 38, 255) \
    NK_COLOR(NK_COLOR_EDIT_CURSOR,              175,175,175,255) \
    NK_COLOR(NK_COLOR_COMBO,                    45, 45, 45, 255) \
    NK_COLOR(NK_COLOR_CHART,                    120,120,120,255) \
    NK_COLOR(NK_COLOR_CHART_COLOR,              45, 45, 45, 255) \
    NK_COLOR(NK_COLOR_CHART_COLOR_HIGHLIGHT,    255, 0,  0, 255) \
    NK_COLOR(NK_COLOR_SCROLLBAR,                40, 40, 40, 255) \
    NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR,         100,100,100,255) \
    NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER,   120,120,120,255) \
    NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE,  150,150,150,255) \
    NK_COLOR(NK_COLOR_TAB_HEADER,               40, 40, 40,255)  \
    NK_COLOR(NK_COLOR_KNOB,                     38, 38, 38, 255) \
    NK_COLOR(NK_COLOR_KNOB_CURSOR,              100,100,100,255) \
    NK_COLOR(NK_COLOR_KNOB_CURSOR_HOVER,        120,120,120,255) \
    NK_COLOR(NK_COLOR_KNOB_CURSOR_ACTIVE,       150,150,150,255)

struct theme g_theme = {0};
struct nk_color theme_get_offset_color(struct nk_color base, int offset);

void theme_init(struct nk_context *ctx)
{
    /*
    g_theme.base            = nk_rgb(38, 42, 54);
    g_theme.background      = nk_rgb(24, 26, 32);
    g_theme.menu_background = nk_rgb(16, 18, 22);
    g_theme.foreground      = nk_rgb(225, 228, 234);
    g_theme.menu_unselected = nk_rgb(120, 125, 135);
    g_theme.alternate       = nk_rgb(66, 135, 220);
    g_theme.selection       = nk_rgb(242, 196, 48);
    g_theme.warning         = nk_rgb(242, 196, 48);
    g_theme.error           = nk_rgb(210, 55, 55);
    g_theme.offset          = nk_rgb(28, 30, 36);
    */

    g_theme.base            = nk_rgb(45, 45, 45);
    g_theme.background      = nk_rgb(30, 30, 30);
    g_theme.menu_background = nk_rgb(22, 22, 22);
    g_theme.foreground      = nk_rgb(215, 218, 224);
    g_theme.menu_unselected = nk_rgb(125, 125, 125);
    g_theme.alternate       = nk_rgb(66, 135, 220);
    g_theme.selection       = nk_rgb(242, 196, 48);
    g_theme.warning         = nk_rgb(242, 196, 48);
    g_theme.error           = nk_rgb(210, 55, 55);
    g_theme.offset          = nk_rgb(30, 30, 30);

    /* Toast */
    g_theme.toast_bg     = nk_rgba(30, 32, 38, 220);
    g_theme.toast_border = nk_rgba(80, 85, 95, 180);
    g_theme.toast_text   = g_theme.foreground;

    /* Modal overlay */
    g_theme.modal_overlay = nk_rgba(0, 0, 0, 140);

    /* File browser */
    g_theme.fb_file_color   = g_theme.foreground;
    g_theme.fb_folder_color = g_theme.selection;
    g_theme.fb_file_color_hover   = theme_get_offset_color(g_theme.fb_file_color, -20);
    g_theme.fb_folder_color_hover = theme_get_offset_color(g_theme.fb_folder_color, -20);

    /* Debugger */
    g_theme.dbg_pc_highlight = g_theme.selection;

    /* Message icons */
    g_theme.msg_warn_icon  = g_theme.selection;
    g_theme.msg_error_icon = g_theme.error;

    /* Selection background */
    g_theme.selection_bg = nk_rgba(242, 196, 48, 25);
    g_theme.selection_active  = theme_get_active_color(g_theme.selection);
    g_theme.selection_shifted = theme_get_shifted_color(g_theme.selection, 1);

    /* Tab bar */
    g_theme.tab_indicator = g_theme.selection;
    g_theme.tab_separator = nk_rgb(55, 58, 68);

    /* Menu section title */
    g_theme.menu_title = g_theme.alternate;

    //g_theme.row_height = 22;
    //g_theme.row_height = 1.25 * ctx->style.font->height;
    g_theme.font_scale = 1;

    theme_update_dimensions(ctx); 

    // Set Colors
    g_theme.all_colors[NK_COLOR_TEXT] = g_theme.foreground;
    g_theme.all_colors[NK_COLOR_WINDOW] = g_theme.background;
    g_theme.all_colors[NK_COLOR_HEADER] = theme_get_offset_color(g_theme.all_colors[NK_COLOR_WINDOW], -5);
    g_theme.all_colors[NK_COLOR_BORDER] = theme_get_offset_color(g_theme.all_colors[NK_COLOR_WINDOW], 20);
    g_theme.all_colors[NK_COLOR_BUTTON] = theme_get_offset_color(g_theme.all_colors[NK_COLOR_WINDOW],  5);
    g_theme.all_colors[NK_COLOR_BUTTON_HOVER] = theme_get_offset_color(g_theme.all_colors[NK_COLOR_WINDOW], -5);
    g_theme.all_colors[NK_COLOR_BUTTON_ACTIVE] = theme_get_offset_color(g_theme.all_colors[NK_COLOR_WINDOW], -10);
    g_theme.all_colors[NK_COLOR_TOGGLE] = theme_get_offset_color(g_theme.all_colors[NK_COLOR_WINDOW],  60);
    g_theme.all_colors[NK_COLOR_TOGGLE_HOVER] = theme_get_offset_color(g_theme.all_colors[NK_COLOR_TEXT], -20);
    g_theme.all_colors[NK_COLOR_TOGGLE_CURSOR] = g_theme.all_colors[NK_COLOR_TEXT];
    g_theme.all_colors[NK_COLOR_SELECT] = g_theme.all_colors[NK_COLOR_WINDOW];
    g_theme.all_colors[NK_COLOR_SELECT_ACTIVE] = theme_get_offset_color(g_theme.all_colors[NK_COLOR_SELECT], -10);
    g_theme.all_colors[NK_COLOR_SLIDER] = theme_get_offset_color(g_theme.all_colors[NK_COLOR_TEXT], -100);
    g_theme.all_colors[NK_COLOR_SLIDER_CURSOR] = theme_get_offset_color(g_theme.all_colors[NK_COLOR_TEXT], -40);
    g_theme.all_colors[NK_COLOR_SLIDER_CURSOR_HOVER] = theme_get_offset_color(g_theme.all_colors[NK_COLOR_TEXT], -40);
    g_theme.all_colors[NK_COLOR_SLIDER_CURSOR_ACTIVE] = theme_get_shifted_color(g_theme.all_colors[NK_COLOR_TEXT],1);
    g_theme.all_colors[NK_COLOR_PROPERTY] = theme_get_offset_color(g_theme.all_colors[NK_COLOR_WINDOW], -7);
    g_theme.all_colors[NK_COLOR_EDIT] = g_theme.all_colors[NK_COLOR_PROPERTY];
    g_theme.all_colors[NK_COLOR_EDIT_CURSOR] = g_theme.all_colors[NK_COLOR_TEXT];
    g_theme.all_colors[NK_COLOR_COMBO] = g_theme.all_colors[NK_COLOR_WINDOW];
    g_theme.all_colors[NK_COLOR_CHART] = g_theme.all_colors[NK_COLOR_SLIDER_CURSOR_HOVER];
    g_theme.all_colors[NK_COLOR_CHART_COLOR] = g_theme.all_colors[NK_COLOR_WINDOW];
    g_theme.all_colors[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgb(255,0,0);
    g_theme.all_colors[NK_COLOR_SCROLLBAR] = theme_get_offset_color(g_theme.all_colors[NK_COLOR_WINDOW], -5);
    g_theme.all_colors[NK_COLOR_SCROLLBAR_CURSOR] = theme_get_offset_color(g_theme.all_colors[NK_COLOR_SCROLLBAR], 60);
    g_theme.all_colors[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = theme_get_offset_color(g_theme.all_colors[NK_COLOR_SCROLLBAR], 80);
    g_theme.all_colors[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = theme_get_offset_color(g_theme.all_colors[NK_COLOR_SCROLLBAR], 110);
    g_theme.all_colors[NK_COLOR_TAB_HEADER] = theme_get_offset_color(g_theme.all_colors[NK_COLOR_WINDOW], -5);
    g_theme.all_colors[NK_COLOR_KNOB] = g_theme.all_colors[NK_COLOR_PROPERTY];
    g_theme.all_colors[NK_COLOR_KNOB_CURSOR] = g_theme.all_colors[NK_COLOR_SCROLLBAR_CURSOR];
    g_theme.all_colors[NK_COLOR_KNOB_CURSOR_HOVER] = g_theme.all_colors[NK_COLOR_SCROLLBAR_CURSOR_HOVER];
    g_theme.all_colors[NK_COLOR_KNOB_CURSOR_ACTIVE] = g_theme.all_colors[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE];

    nk_style_from_table(ctx, g_theme.all_colors);
}

struct nk_color theme_get_offset_color(struct nk_color base, int offset)
{
    struct nk_color new;
    new.r = base.r + offset;
    new.g = base.g + offset;
    new.b = base.b + offset;
    new.a = base.a;

    return new;
}

struct theme *theme_get_theme(void)
{
    return &g_theme;
}

struct nk_color theme_get_active_color(struct nk_color col)
{
    struct nk_color new;

    new.r = col.r >> 1;
    new.g = col.g >> 1;
    new.b = col.b >> 1;
    new.a = col.a;

    return new;
}

struct nk_color theme_get_shifted_color(struct nk_color col, int shift)
{
    struct nk_color new;

    if (shift < 0) {
        shift = shift * -1;
        new.r = col.r << shift;
        new.g = col.g << shift;
        new.b = col.b << shift;
    }
    else {
        new.r = col.r >> shift;
        new.g = col.g >> shift;
        new.b = col.b >> shift;
    }
    new.a = col.a;

    return new;
}

struct nk_color theme_get_transparent_color(struct nk_color col)
{
    return col;
}

void theme_update_window_columns(int window_w)
{
    g_theme.columns[0] = window_w/30;
    g_theme.columns[1] = g_theme.columns[2] = g_theme.columns[3] = window_w/3;
    /* Options menu needs ~900px for 5 tabs (810px) + chevron + margins */
    g_theme.use_compact_menu = (window_w < 900);
}

void theme_calculate_selection_rect(struct nk_context *ctx) 
{
    g_theme.selection_rect.x = (g_theme.row_height-2) * -1;
    g_theme.selection_rect.y = (g_theme.selection_rect.x / 4);
    g_theme.selection_rect.w = g_theme.selection_rect.x * -2.0;
    g_theme.selection_rect.h = (g_theme.selection_rect.y * -2) + ctx->style.window.spacing.y*2;
}

void theme_update_dimensions(struct nk_context *ctx)
{
    float current_height = ctx->style.font->height * g_theme.font_scale;
    g_theme.menu_label_width_active = g_theme.menu_label_width;
    g_theme.select_label_width_active = g_theme.select_label_width;
    g_theme.menu_widget_width_active = g_theme.menu_widget_min_width;
    if (current_height == g_theme.last_font_height)
        return;
    g_theme.last_font_height = current_height;

    g_theme.row_height = current_height;
    g_theme.row_height_eighth = g_theme.row_height / 8;
    g_theme.row_height_half   = g_theme.row_height / 2;
    g_theme.row_height_1_5    = g_theme.row_height * 1.5f;
    g_theme.row_height_double = g_theme.row_height * 2;
    float text_width = ctx->style.font->width(ctx->style.font->userdata, ctx->style.font->height, "demo_selector_max", strlen("demo_selector_max"));
    g_theme.menu_label_width = text_width * 1.4;
    text_width = ctx->style.font->width(ctx->style.font->userdata, ctx->style.font->height, " Atari 400/800 XXXXX", strlen(" Atari 400/800 XXXXX"));
    g_theme.select_label_width = text_width * 1;
    /* Minimum column width needed to show widget_select without clipping:
       4 static columns + 3 inter-column spacings + 2x group padding */
    float grp_pad = ctx->style.window.group_padding.x;
    float spacing = ctx->style.window.spacing.x;
    g_theme.menu_widget_min_width = (int)(g_theme.menu_label_width
                                          + 2 * g_theme.row_height
                                          + g_theme.select_label_width
                                          + 3 * spacing
                                          + 2 * grp_pad);
    g_theme.menu_label_width_active = g_theme.menu_label_width;
    g_theme.select_label_width_active = g_theme.select_label_width;
    g_theme.menu_widget_width_active = g_theme.menu_widget_min_width;
    theme_calculate_selection_rect(ctx);
}

void theme_push_selected_button_color(struct nk_context *ctx)
{
    nk_style_push_color(ctx, &ctx->style.text.color, g_theme.selection);
    nk_style_push_color(ctx, &ctx->style.button.text_normal, g_theme.selection);
    nk_style_push_color(ctx, &ctx->style.button.text_hover,  g_theme.selection);
    nk_style_push_color(ctx, &ctx->style.button.text_active, g_theme.selection_active);
}

void theme_pop_selected_button_color(struct nk_context *ctx)
{
    nk_style_pop_color(ctx);
    nk_style_pop_color(ctx);
    nk_style_pop_color(ctx);
    nk_style_pop_color(ctx);
}
