/*
 * File: Common_Screen_Elements.c
 *
 * Created: Created: Sunday October 2025 19:57:27
 *   Author: Chris
 */
#include "Common_Screen_Elements.h"

// ============================================================================================
// Includes
#include "../Display_Color.h"
#include "../Display_Config.h"
#include "../Display_Shapes.h"
#include "../Display_Objects.h"

#include "../Hue.h"
#include "../EEPROM_M24C64.h"
#include "../MIDI_Note_List.h"
#include "../Command_Definition.h"


// ============================================================================================
// Defines
#define PAUSE_LIGHT_COLOR_RGB565    DISPLAY_COLOR_FROM_RGB888(_EEPROM_Content.Pause_Light_Configuration[LED_Channel_1].Color.R, _EEPROM_Content.Pause_Light_Configuration[LED_Channel_1].Color.G, _EEPROM_Content.Pause_Light_Configuration[LED_Channel_1].Color.B)


// ============================================================================================
// Variables
extern const uint8_t _Font_DejaVu_Sans_Mono_10x17[];
extern const uint8_t _Font_DejaVu_Sans_Mono_15x25[];
extern const uint8_t _Font_DejaVu_Sans_Mono_Bold_11x17[];
extern const uint8_t _Font_DejaVu_Sans_Mono_Bold_15x26[];

extern const uint16_t _Image_Forest_Pine_Midi_64x64[];
extern const uint16_t _Image_Steel_Blue_Jam_Happy_64x64[];
extern const uint16_t _Image_Stone_Blue_Light_On_64x64[];

extern volatile bool _MIDI_To_Light_Enabled;
extern Info_Last_Received_Note_t _Info_Last_Applied_Note[NUM_LED_CHANNELS];
extern uint8_t _Current_Duty_Cylces[NUM_LED_CHANNELS][NUM_LED_COLORS];
extern volatile Pause_Light_Timer_s	_Pause_Light_Timer[NUM_LED_CHANNELS];


// Variables and Objects IDs for the MIDI Mode Activity
static Object_ID _Object_Midi_Text_MIDI_Enabled;
static Object_ID _Object_Midi_Text_MIDI_Last_Applied;
static Object_ID _Object_Midi_Text_Pause_Light_Enabled;
static Object_ID _Object_Midi_Text_Pause_Light_Active;
static Object_ID _Object_Midi_Text_Pause_Light_Counter;
static Object_ID _Object_Midi_Text_Pause_Light_ValueBar;

static float _Pause_Light_Timeout_s;
static uint32_t _Pause_Light_Timeout_Ticks;
static uint32_t _Pause_Light_FadeOut_Counter;

// Variables and Objects IDs for the JAM Mode Activity
static Object_ID _Object_Jam_Current_Hue_Angle;
static Object_ID _Object_Jam_Timeout_ValueBar;

static uint32_t _Jam_Hue_Angle_Now;
static uint32_t _Jam_Hue_Angle_Next;
static float    _Jam_Hue_Angle_Timer_s;
static uint32_t _Jam_Hue_Angle_Timer_Ticks;

// Objects IDs for the Const Mode Activity
static Object_ID _Object_Const_Color_Circle;
static Object_ID _Object_Const_Color_Text_1, _Object_Const_Color_Text_2;


// ============================================================================================
// Function Declarations
void Common_Screen_Element_Init_Mode_Activity_Midi();
void Common_Screen_Element_Init_Mode_Activity_Jam();
void Common_Screen_Element_Init_Mode_Activity_Const();

void Common_Screen_Element_Tick_Mode_Activity_Midi();
void Common_Screen_Element_Tick_Mode_Activity_Jam();
void Common_Screen_Element_Tick_Mode_Activity_Const();


/*******************************************************************
    Functions
*******************************************************************/
void Common_Screen_Element_Init_Current_Mode(Mode mode)
{
    uint16_t* Image = NULL;
    char Mode_Name[20];

    switch (mode)
    {
    case MIDI:      sprintf(Mode_Name, "MIDI");       Image = (uint16_t*)_Image_Forest_Pine_Midi_64x64; break;
    case JAM:       sprintf(Mode_Name, "Jam");        Image = (uint16_t*)_Image_Steel_Blue_Jam_Happy_64x64; break;
    case CONSTANT:  sprintf(Mode_Name, "Constant");   Image = (uint16_t*)_Image_Stone_Blue_Light_On_64x64; break;
    }
    
    Display_Objects_Add_Image(CENTER_MIDDLE, BOTH_IN_PERCENT, 50, 40, NOT_SELECTABLE, Image, 0, NO_STYLE, NO_ANIMATION);

    char Title[30];
    sprintf(Title, "Mode: %s", Mode_Name);

    Font_ID Font_Title = Display_Objects_Add_Font(_Font_DejaVu_Sans_Mono_15x25, 0);
    Display_Objects_Add_Text(CENTER_MIDDLE, BOTH_IN_PERCENT, 50, 65, NOT_SELECTABLE, Title, Font_Title, DISPLAY_COLOR_LIGHTGREY, NO_STYLE, NO_ANIMATION);
}

void Common_Screen_Element_Init_Mode_Activity(Mode mode)
{
    switch (mode)
    {
    case MIDI:      Common_Screen_Element_Init_Mode_Activity_Midi();    break;
    case JAM:       Common_Screen_Element_Init_Mode_Activity_Jam();     break;
    case CONSTANT:  Common_Screen_Element_Init_Mode_Activity_Const();   break;
    }
}

void Common_Screen_Element_Tick_Mode_Activity(Mode mode)
{
    switch (mode)
    {
    case MIDI:      Common_Screen_Element_Tick_Mode_Activity_Midi();    break;
    case JAM:       Common_Screen_Element_Tick_Mode_Activity_Jam();     break;
    case CONSTANT:  Common_Screen_Element_Tick_Mode_Activity_Const();   break;
    }
}


/*******************************************************************
    Internal Functions
*******************************************************************/
void Common_Screen_Element_Init_Mode_Activity_Midi()
{
    _Pause_Light_Timeout_s = 0.0f;
    _Pause_Light_Timeout_Ticks = 0;
    
    const int16_t Text_Y_Percent_Distance = 8;

    char MIDI_Settings[100];

    sprintf(MIDI_Settings, "Ch %02u / Octave %+d", _EEPROM_Content.Channel_MIDI_Configuration[LED_Channel_1].MIDI_Channel+1, _EEPROM_Content.Channel_MIDI_Configuration[LED_Channel_1].Octave);

    Font_ID Font_Regular = Display_Objects_Add_Font(_Font_DejaVu_Sans_Mono_10x17, 0);
    Font_ID Font_Bold = Display_Objects_Add_Font(_Font_DejaVu_Sans_Mono_Bold_11x17, 0);

    int16_t Midi_Y_Percent = 20;
    Display_Objects_Add_Text(LEFT_MIDDLE, BOTH_IN_PERCENT, 20, Midi_Y_Percent, NOT_SELECTABLE, "Midi to Light", Font_Bold, DISPLAY_COLOR_LIGHTGREY, NO_STYLE, NO_ANIMATION);
    Midi_Y_Percent += Text_Y_Percent_Distance;

    _Object_Midi_Text_MIDI_Enabled = Display_Objects_Add_Text(LEFT_MIDDLE, BOTH_IN_PERCENT, 20, Midi_Y_Percent, NOT_SELECTABLE, "", Font_Regular, DISPLAY_COLOR_BLACK, NO_STYLE, NO_ANIMATION);
    Midi_Y_Percent += Text_Y_Percent_Distance;

    Display_Objects_Add_Text(LEFT_MIDDLE, BOTH_IN_PERCENT, 20, Midi_Y_Percent, NOT_SELECTABLE, MIDI_Settings, Font_Regular, DISPLAY_COLOR_LIGHTGREY, NO_STYLE, NO_ANIMATION);
    Midi_Y_Percent += Text_Y_Percent_Distance;

    _Object_Midi_Text_MIDI_Last_Applied = Display_Objects_Add_Text(LEFT_MIDDLE, BOTH_IN_PERCENT, 20, Midi_Y_Percent, NOT_SELECTABLE, "", Font_Regular, DISPLAY_COLOR_LIGHTGREY, NO_STYLE, NO_ANIMATION);



    int16_t Pause_Light_Y_Percent = 57;
    Display_Objects_Add_Text(LEFT_MIDDLE, BOTH_IN_PERCENT, 20, Pause_Light_Y_Percent, NOT_SELECTABLE, "Pause Light", Font_Bold, DISPLAY_COLOR_LIGHTGREY, NO_STYLE, NO_ANIMATION);
    Pause_Light_Y_Percent += Text_Y_Percent_Distance;

    _Object_Midi_Text_Pause_Light_Enabled = Display_Objects_Add_Text(LEFT_MIDDLE, BOTH_IN_PERCENT, 20, Pause_Light_Y_Percent, NOT_SELECTABLE, "", Font_Regular, DISPLAY_COLOR_BLACK, NO_STYLE, NO_ANIMATION);
    Pause_Light_Y_Percent += Text_Y_Percent_Distance;

    _Object_Midi_Text_Pause_Light_Active = Display_Objects_Add_Text(LEFT_MIDDLE, BOTH_IN_PERCENT, 20, Pause_Light_Y_Percent, NOT_SELECTABLE, "", Font_Regular, DISPLAY_COLOR_BLACK, NO_STYLE, NO_ANIMATION);
    Pause_Light_Y_Percent += Text_Y_Percent_Distance;

    _Object_Midi_Text_Pause_Light_ValueBar = Display_Objects_Add_Value_Bar_Arc(BOTH_IN_PERCENT, 50, 50, NOT_SELECTABLE, &_Pause_Light_Timeout_Ticks,
        (uint32_t)(_EEPROM_Content.Pause_Light_Configuration[LED_Channel_1].Timeout * 1000 / TIMER_INTERVALL_LED_UPDATE_ms), 1,
        (uint32_t)(_EEPROM_Content.Pause_Light_Configuration[LED_Channel_1].Timeout * 1000 / TIMER_INTERVALL_LED_UPDATE_ms), 10,
        PAUSE_LIGHT_COLOR_RGB565, 110, 4, ARC_FRAME_AUTO_STEPS, -90, 270, NO_STYLE, NO_ANIMATION);

    _Object_Midi_Text_Pause_Light_Counter = Display_Objects_Add_Float(LEFT_MIDDLE, BOTH_IN_PERCENT, 20, Pause_Light_Y_Percent, NOT_SELECTABLE, &_Pause_Light_Timeout_s, "%04.2fs", Font_Regular, DISPLAY_COLOR_LIGHTGREY, NO_STYLE, NO_ANIMATION);
}

void Common_Screen_Element_Init_Mode_Activity_Jam()
{
    _Jam_Hue_Angle_Now = 0;
    _Jam_Hue_Angle_Next = 0;
    _Jam_Hue_Angle_Timer_s = 0.0;
    _Jam_Hue_Angle_Timer_Ticks = 0;

    const int16_t Text_Y_Percent_Distance = 8;

    Font_ID Font_Regular = Display_Objects_Add_Font(_Font_DejaVu_Sans_Mono_10x17, 0);
    Font_ID Font_Bold = Display_Objects_Add_Font(_Font_DejaVu_Sans_Mono_Bold_11x17, 0);

    int16_t Text_Y_Percent = 35;
    Display_Objects_Add_Text(LEFT_MIDDLE, BOTH_IN_PERCENT, 20, Text_Y_Percent, NOT_SELECTABLE, "Jam Mode", Font_Bold, DISPLAY_COLOR_LIGHTGREY, NO_STYLE, NO_ANIMATION);
    Text_Y_Percent += Text_Y_Percent_Distance;
    
    Display_Objects_Add_Integer(LEFT_MIDDLE, BOTH_IN_PERCENT, 20, Text_Y_Percent, NOT_SELECTABLE, (int*)&_Jam_Hue_Angle_Now, "Now:  %d Deg", Font_Regular, DISPLAY_COLOR_LIGHTGREY, NO_STYLE, NO_ANIMATION);
    Text_Y_Percent += Text_Y_Percent_Distance;

    Display_Objects_Add_Integer(LEFT_MIDDLE, BOTH_IN_PERCENT, 20, Text_Y_Percent, NOT_SELECTABLE, (int*)&_Jam_Hue_Angle_Next, "Next: %d Deg", Font_Regular, DISPLAY_COLOR_LIGHTGREY, NO_STYLE, NO_ANIMATION);
    Text_Y_Percent += Text_Y_Percent_Distance;

    Display_Objects_Add_Float(LEFT_MIDDLE, BOTH_IN_PERCENT, 20, Text_Y_Percent, NOT_SELECTABLE, &_Jam_Hue_Angle_Timer_s, "%04.2fs", Font_Regular, DISPLAY_COLOR_LIGHTGREY, NO_STYLE, NO_ANIMATION);

    _Object_Jam_Current_Hue_Angle = Display_Objects_Add_Value_Bar_Arc(BOTH_IN_PERCENT, 50, 50, NOT_SELECTABLE, &_Jam_Hue_Angle_Now, 359, 0, 1, 400, DISPLAY_COLOR_RED, 115, 4, ARC_FRAME_AUTO_STEPS, -90, 270, NO_STYLE, NO_ANIMATION);
    _Object_Jam_Timeout_ValueBar = Display_Objects_Add_Value_Bar_Arc(BOTH_IN_PERCENT, 50, 50, NOT_SELECTABLE, &_Jam_Hue_Angle_Timer_Ticks, Mode_Manager_Jam_Get_Duration_Tick(), 0, 1000, 1000, DISPLAY_COLOR_LIGHTGREY, 105, 4, ARC_FRAME_AUTO_STEPS, -90, 270, NO_STYLE, NO_ANIMATION);
}

void Common_Screen_Element_Init_Mode_Activity_Const()
{
    Font_ID Font = Display_Objects_Add_Font(_Font_DejaVu_Sans_Mono_Bold_11x17, 0);
    
    _Object_Const_Color_Circle = Display_Objects_Add_Circle_Filled(CENTER_MIDDLE, BOTH_IN_PERCENT, 50, 35, NOT_SELECTABLE, DISPLAY_COLOR_BLACK, 40, NO_STYLE, NO_ANIMATION);
    _Object_Const_Color_Text_1 = Display_Objects_Add_Text(CENTER_BOTTOM, BOTH_IN_PERCENT, 50, 68, NOT_SELECTABLE, "Constant Light", Font, DISPLAY_COLOR_LIGHTGREY, NO_STYLE, NO_ANIMATION);
    _Object_Const_Color_Text_2 = Display_Objects_Add_Text(CENTER_TOP, BOTH_IN_PERCENT, 50, 70, NOT_SELECTABLE, "is on", Font, DISPLAY_COLOR_LIGHTGREY, NO_STYLE, NO_ANIMATION);
}

void Common_Screen_Element_Tick_Mode_Activity_Midi()
{
    char MIDI_Last_Applied[100];
    char Event[4];
    char Note[3];

    if(_Info_Last_Applied_Note[LED_Channel_1].Event == MIDI_EVENT_NOTE_ON) {
        sprintf(Event, "On");
    }
    else if(_Info_Last_Applied_Note[LED_Channel_1].Event == MIDI_EVENT_NOTE_OFF) {
       sprintf(Event, "Off");
    } else
    {
        sprintf(Event, "-");
    }

    if(_Info_Last_Applied_Note[LED_Channel_1].Note_In_Octave != NO_NOTE) {
        sprintf(Note, "%s", _MIDI_Note_List[_Info_Last_Applied_Note[LED_Channel_1].Note_In_Octave].Tone_Name);
    }
    else {
        sprintf(Note, "-");
    }

    sprintf(MIDI_Last_Applied, "Note %s %s (%u)", Note, Event, _Info_Last_Applied_Note[LED_Channel_1].Velocity);
    
    Display_Objects_Update_Text(_Object_Midi_Text_MIDI_Enabled, _MIDI_To_Light_Enabled == true ? "Enabled" : "Disabled");
    Display_Objects_Update_Text(_Object_Midi_Text_MIDI_Last_Applied, MIDI_Last_Applied);
    Display_Objects_Update_Text(_Object_Midi_Text_Pause_Light_Enabled, _EEPROM_Content.Pause_Light_Configuration[LED_Channel_1].Enabled > 0 ? "Enabled" : "Disabled");
    Display_Objects_Update_Text(_Object_Midi_Text_Pause_Light_Active, _Pause_Light_Timer[LED_Channel_1].Is_Active == true ? "On" : "Off");

    Display_Objects_Update_Color(_Object_Midi_Text_MIDI_Enabled, _MIDI_To_Light_Enabled == true ? DISPLAY_COLOR_GREEN : DISPLAY_COLOR_RED);
    Display_Objects_Update_Color(_Object_Midi_Text_Pause_Light_Enabled, _EEPROM_Content.Pause_Light_Configuration[LED_Channel_1].Enabled > 0 ? DISPLAY_COLOR_GREEN : DISPLAY_COLOR_RED);
    Display_Objects_Update_Color(_Object_Midi_Text_Pause_Light_Active, _Pause_Light_Timer[LED_Channel_1].Is_Active == true ? DISPLAY_COLOR_GREEN : DISPLAY_COLOR_RED);

    _Pause_Light_Timeout_s = _EEPROM_Content.Pause_Light_Configuration[LED_Channel_1].Timeout - ((float)(_Pause_Light_Timer[LED_Channel_1].Timer * TIMER_INTERVALL_LED_UPDATE_ms)) / 1000.0f;

    if(_Pause_Light_Timeout_s < 0.01f) {
        if(_Pause_Light_FadeOut_Counter < 60) {
            _Pause_Light_FadeOut_Counter++;
        }
        if(_Pause_Light_FadeOut_Counter >= 20) {
            // Display_Objects_Update_Color(_Object_Midi_Text_MIDI_Last_Applied, Display_Color_Interpolate_Float(DISPLAY_COLOR_LIGHTGREY, DISPLAY_COLOR_BLACK, (float)(_Pause_Light_FadeOut_Counter-20) / 40.0f));
            Display_Objects_Update_Color(_Object_Midi_Text_Pause_Light_Counter, Display_Color_Interpolate_Float(DISPLAY_COLOR_LIGHTGREY, DISPLAY_COLOR_BLACK, (float)(_Pause_Light_FadeOut_Counter-20) / 40.0f));
            Display_Objects_Update_Color(_Object_Midi_Text_Pause_Light_ValueBar, Display_Color_Interpolate_Float(PAUSE_LIGHT_COLOR_RGB565, DISPLAY_COLOR_BLACK, (float)(_Pause_Light_FadeOut_Counter-20) / 40.0f));
        }
    }
    else {
        _Pause_Light_FadeOut_Counter = 0;
        // Display_Objects_Update_Color(_Object_Midi_Text_MIDI_Last_Applied, DISPLAY_COLOR_LIGHTGREY);
        Display_Objects_Update_Color(_Object_Midi_Text_Pause_Light_Counter, DISPLAY_COLOR_LIGHTGREY);
        Display_Objects_Update_Color(_Object_Midi_Text_Pause_Light_ValueBar, PAUSE_LIGHT_COLOR_RGB565);
    }

    uint32_t Total_Pause_Light_Timeout_Ticks = (uint32_t)(_EEPROM_Content.Pause_Light_Configuration[LED_Channel_1].Timeout * 1000 / TIMER_INTERVALL_LED_UPDATE_ms);
    _Pause_Light_Timeout_Ticks = Total_Pause_Light_Timeout_Ticks - _Pause_Light_Timer[LED_Channel_1].Timer;
}

void Common_Screen_Element_Tick_Mode_Activity_Jam()
{
    LED_Data_t Hue_Color;

    _Jam_Hue_Angle_Now = Mode_Manager_Jam_Get_Current_Angle();
    _Jam_Hue_Angle_Next = Mode_Manager_Jam_Get_Next_Angle();
    _Jam_Hue_Angle_Timer_Ticks = Mode_Manager_Jam_Get_Time_Left_Tick();
    _Jam_Hue_Angle_Timer_s = (float)(_Jam_Hue_Angle_Timer_Ticks * 40) / 1000.0f;
    
    Hue_Color.Pixel = Hue_Get_Color_From_Angle(_Jam_Hue_Angle_Now);
    Display_Objects_Update_Color(_Object_Jam_Current_Hue_Angle, DISPLAY_COLOR_FROM_RGB888(Hue_Color.R, Hue_Color.G, Hue_Color.B));
    Display_Objects_Update_Max_Min(_Object_Jam_Timeout_ValueBar, Mode_Manager_Jam_Get_Duration_Tick(), 0);
}

void Common_Screen_Element_Tick_Mode_Activity_Const()
{
    Display_Objects_Update_Color(_Object_Const_Color_Circle, DISPLAY_COLOR_FROM_RGB888(_Current_Duty_Cylces[LED_Channel_1][R], _Current_Duty_Cylces[LED_Channel_1][G], _Current_Duty_Cylces[LED_Channel_1][B]));
}
