/*
 * File: Screen_Settings_Hierarchical_Menu.c
 *
 * Created: Created: Sunday September 2025 19:19:34
 *   Author: Chris
 */


// ============================================================================================
// Includes
#include "../Screens.h"
#include "../UI_Control.h"
#include "../Hierarchical_Menu.h"
#include "../Command_Definition.h"

#include "../Display.h"
#include "../Display_Objects.h"
#include "../Display_Default_Configurations.h"

#include <string.h>


// ============================================================================================
// Defines


// ============================================================================================
// Variables
extern const unsigned char 	_Font_DejaVu_Sans_Mono_6x12[];
extern const unsigned char 	_Font_DejaVu_Sans_Mono_7x15[];
extern const unsigned char 	_Font_DejaVu_Sans_Mono_Bold_7x15[];
extern const unsigned char 	_Font_DejaVu_Sans_Mono_Bold_15x26[];

static const Hierarchical_Menu* _Menu = NULL;
static const Menu_List* _Current_List = NULL;

static int32_t _Selected_Item;
static int32_t _Scroll_Offset;
static int32_t _Visible_Items;


// ============================================================================================
// Function Declarations
void Screen_Setup_Settings_Hierarchical_Menu(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, const Hierarchical_Menu* menu, const Menu_List* list, int32_t selected_item);

static void Screen_Init                (Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration);
static void Screen_Tick                (void);
static void Screen_Click               (uint button_return_value);
static void Screen_Touch_Event         (int16_t x, int16_t y);
static void Screen_Action_CW           (Object_ID object_id);
static void Screen_Action_CCW          (Object_ID object_id);
static void Screen_On_Object_Focused   (Object_ID object_id);
static void Screen_On_Object_Defocused (Object_ID object_id);
static void Screen_On_Object_Select    (Object_ID object_id);
static void Screen_On_Object_Deselect  (Object_ID object_id);

static void Navigate_To_List(const Menu_List* new_list);
static void Handle_Back_Navigation(void);
static void Calculate_Scroll_Offset(void);
static void Handle_Item_Selection(void);


/*******************************************************************
    Functions
*******************************************************************/
void Screen_Setup_Settings_Hierarchical_Menu(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, const Hierarchical_Menu* menu, const Menu_List* list, int32_t selected_item)
{   
    _Menu = menu;
    _Current_List = list;
    _Selected_Item = selected_item;
    
    Screen_Init(direction_out, direction_in, type, frame_duration);
    
   
    _Scroll_Offset = 0;
    _Visible_Items = _Configuration_Menu_Hierarchical_Default.Visible_Items;
}

void Screen_Init(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration)
{
    _Screen_Tick                   = Screen_Tick;
    _Screen_Click                  = Screen_Click;
    _Screen_Touch_Event            = Screen_Touch_Event;
    _Screen_Action_CW              = Screen_Action_CW;
    _Screen_Action_CCW             = Screen_Action_CCW;
    _Screen_On_Objects_Focused     = Screen_On_Object_Focused;
    _Screen_On_Objects_Defocused   = Screen_On_Object_Defocused;
    _Screen_On_Object_Select       = Screen_On_Object_Select;
    _Screen_On_Object_Deselect     = Screen_On_Object_Deselect;

    Display_Objects_Clear();
    Display_Screen_Transition_Start(direction_out, direction_in, type, frame_duration);


    //////////////////////////////
    // Add Display Objects here //
    //////////////////////////////
    Display_Objects_Add_Menu_Hierarchical(&_Current_List, &_Selected_Item, &_Scroll_Offset, &_Configuration_Menu_Hierarchical_Default);

    Calculate_Scroll_Offset();
    Display_Select_Object();
}

void Screen_Tick(void)
{

}

void Screen_Click(uint button_return_value)
{

}

void Screen_Touch_Event(int16_t x, int16_t y)
{

}

void Screen_Action_CW(Object_ID object_id)
{
    // Move selection down (the renderer will automatically show the change)
    UI_Control_Selector_Inc(&_Selected_Item, 0, (int32_t)_Current_List->Item_Count - 1, false);
    Calculate_Scroll_Offset();
}

void Screen_Action_CCW(Object_ID object_id)
{
    // Move selection up (the renderer will automatically show the change)
    UI_Control_Selector_Dec(&_Selected_Item, 0, (int32_t)_Current_List->Item_Count - 1, false);
    Calculate_Scroll_Offset();
}

void Screen_On_Object_Focused(Object_ID object_id)
{

}

void Screen_On_Object_Defocused(Object_ID object_id)
{

}

void Screen_On_Object_Select(Object_ID object_id)
{

}

void Screen_On_Object_Deselect(Object_ID object_id)
{
    Handle_Item_Selection();
}


/*******************************************************************
    Internal Functions
*******************************************************************/
void Navigate_To_List(const Menu_List* new_list)
{
    if (new_list == NULL) {
        return;
    }
    
    // Update menu state
    _Current_List = new_list;
    _Selected_Item = 0;
    _Scroll_Offset = 0;
        
    Calculate_Scroll_Offset();
    Display_Select_Object();
}

void Handle_Back_Navigation(void)
{
    if (_Current_List->Parent != NULL)
    {
        // Navigate to parent list
        const Menu_List* Parent_List = _Current_List->Parent->Containing_List;
        
        // Find the index of the item that led to current list
        _Selected_Item = 0;
        for (uint32_t i = 0; i < Parent_List->Item_Count; i++)
        {
            if (Parent_List->Items[i].List == _Current_List) {
                _Selected_Item = i;
                break;
            }
        }
        
        _Current_List = Parent_List;
        
        Calculate_Scroll_Offset();
        Display_Select_Object();
    }
    else if (_Menu->Parent_Function != NULL)
    {
        // Exit to parent screen
        _Menu->Parent_Function(TRANSITION_DOWN, TRANSITION_DOWN, SCREEN_TRANSITION_DEFAULT_EASING,  SCREEN_TRANSITION_DEFAULT_FRAMES, _Menu->Parent_Selected_Setting);
    }
}

void Calculate_Scroll_Offset(void)
{
    // Auto-scroll to keep selected item visible
    if (_Selected_Item < _Scroll_Offset) {
        _Scroll_Offset = 0;
    }
    else {
        _Scroll_Offset = _Selected_Item - _Visible_Items + 1;
    }
   
    // Ensure scroll offset is within bounds
    int32_t Max_Scroll = (int32_t)_Current_List->Item_Count - _Visible_Items;
    if (Max_Scroll < 0) {
        Max_Scroll = 0;
    }
    
    if (_Scroll_Offset > Max_Scroll) {
        _Scroll_Offset = Max_Scroll;
    }

    if (_Scroll_Offset < 0) {
        _Scroll_Offset = 0;
    }
}

void Handle_Item_Selection(void)
{
    if (_Selected_Item < 0 || _Selected_Item >= (int32_t)_Current_List->Item_Count) {
        return;
    }
    
    const Menu_Item* Selected_Item = &_Current_List->Items[_Selected_Item];
    
    if (Selected_Item->Is_Back) {
        Handle_Back_Navigation();
        return;
    }
    
    if (Selected_Item->List != NULL) {
        Navigate_To_List(Selected_Item->List);
        return;
    }

    switch(Selected_Item->Type)
    {
        case BOOL:
            Screen_Setup_Select_Bool(TRANSITION_LEFT, TRANSITION_UP, SCREEN_TRANSITION_DEFAULT_EASING, SCREEN_TRANSITION_DEFAULT_FRAMES, (char*)Selected_Item->Variable_Title, strlen(Selected_Item->Variable_Title), (uint8_t*)Selected_Item->Variable, _Menu, Selected_Item->Containing_List, _Selected_Item);
            break;

        case RGB:
            Screen_Setup_Select_RGB(TRANSITION_LEFT, TRANSITION_UP, SCREEN_TRANSITION_DEFAULT_EASING, SCREEN_TRANSITION_DEFAULT_FRAMES, (char*)Selected_Item->Variable_Title, strlen(Selected_Item->Variable_Title), (LED_Data_t*)Selected_Item->Variable, _Menu, Selected_Item->Containing_List, _Selected_Item);
            break;
        
        case NONE:
        default:
            break;
    }
}