#include "menu.h"
#include "graphics.h"
#include "fonts/font.h"
#include "display.h"

static const uint16_t entry_height = 40;
static const uint16_t padding_x = 10;
static const uint16_t padding_y = 0;
static const pixel_t enabled_text_color = MAKE_PIXEL(255, 255, 255);
static const pixel_t disabled_text_color = MAKE_PIXEL(128, 128, 128);
static const pixel_t entry_bg_color = MAKE_PIXEL(0, 0, 0);
static const pixel_t highlighted_bg_color = MAKE_PIXEL(50, 50, 50);
static const pixel_t highlighted_text_color = MAKE_PIXEL(255, 255, 0);

void draw_menu_entry(volatile pixel_t *const framebuffer, const graphical_menu_t *const menu, uint8_t entry_idx)
{
    const uint16_t y_pos = entry_idx * entry_height;
    const graphical_menu_entry_t *entry = &menu->layout->entries[entry_idx];
    const bool is_highlighted = (entry_idx == menu->selected_entry_idx) && entry->enabled;
    
    // Draw entry background - use highlighted color if this is the selected entry
    pixel_t bg_color = is_highlighted ? highlighted_bg_color : entry_bg_color;
    DrawBox(0, y_pos, DISPLAY_WIDTH, entry_height, bg_color);
    
    // Draw entry text - use highlighted color if selected, otherwise use enabled/disabled color
    pixel_t text_color;
    if (is_highlighted)
    {
        text_color = highlighted_text_color;
    }
    else
    {
        text_color = entry->enabled ? enabled_text_color : disabled_text_color;
    }
    
    // Calculate baseline from top position: baseline = top + (line_height - base_line)
    const uint16_t text_baseline_y = y_pos + padding_y + (roboto_bold_font.line_height - roboto_bold_font.base_line);
    draw_string(framebuffer, &runescape_font, 
                padding_x, text_baseline_y, 
                entry->title, text_color);
}

void draw_menu(volatile pixel_t *const framebuffer, const graphical_menu_t *const menu)
{
    DrawBox(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT, entry_bg_color);
    
    for (uint8_t i = 0; i < menu->layout->num_entries; i++)
    {
        draw_menu_entry(framebuffer, menu, i);
    }
}

void partial_redraw_menu(volatile pixel_t *const framebuffer, graphical_menu_t *const menu, uint8_t old_highlighted_entry_idx, uint8_t new_highlighted_entry_idx)
{
    draw_menu_entry(framebuffer, menu, old_highlighted_entry_idx);
    draw_menu_entry(framebuffer, menu, new_highlighted_entry_idx);

}

void select_menu_entry(graphical_menu_t *const menu)
{
    // Ensure selected_entry_idx is within bounds
    if (menu->selected_entry_idx >= menu->layout->num_entries)
    {
        return;
    }
    
    const graphical_menu_entry_t *entry = &menu->layout->entries[menu->selected_entry_idx];
    
    // Only select if the entry is enabled
    if (entry->enabled && entry->selected_callback_function != NULL)
    {
        entry->selected_callback_function(entry->selected_callback_function_args);
    }
}

void set_selected_menu_entry_idx(volatile pixel_t *const framebuffer, graphical_menu_t *const menu, uint8_t idx)
{
    const uint16_t old_highlighted_entry_idx = menu->selected_entry_idx;


    // Handle case where the last entry is disabled
    if (idx == menu->layout->num_entries - 1)
    {
        while (!menu->layout->entries[idx].enabled)
        {
            idx--;
        }
    }

    // Only allow selecting enabled entries
    while (!menu->layout->entries[idx].enabled)
    {
        if (idx > menu->selected_entry_idx)
        {
            idx--;
        }
        else
        {
            idx++;
        }
    }

    // Clamp the index to valid range
    if (idx >= menu->layout->num_entries)
    {
        if (menu->layout->num_entries == 0) return;
        idx = menu->layout->num_entries - 1;
    }

    menu->selected_entry_idx = idx;
    partial_redraw_menu(framebuffer, menu, old_highlighted_entry_idx, idx);
}

void decrement_selected_menu_entry_idx(volatile pixel_t *const framebuffer, graphical_menu_t *const menu)
{
    if (menu->selected_entry_idx == 0)
    {
        set_selected_menu_entry_idx(framebuffer, menu, menu->layout->num_entries - 1);
        return;
    }
    set_selected_menu_entry_idx(framebuffer, menu, menu->selected_entry_idx - 1);
}

void increment_selected_menu_entry_idx(volatile pixel_t *const framebuffer, graphical_menu_t *const menu)
{
    if (menu->selected_entry_idx == menu->layout->num_entries - 1)
    {
        set_selected_menu_entry_idx(framebuffer, menu, 0);
        return;
    }
    set_selected_menu_entry_idx(framebuffer, menu, menu->selected_entry_idx + 1);
}