/*
 * File: Serial_Command.c
 *
 * Created: Created: Sunday October 2025 09:41:07
 *   Author: Chris
 */
#include "Serial_Command.h"


// ============================================================================================
// Includes
#include "Convert.h"
#include "USB_Serial.h"
#include "Mode_Manager.h"
#include "EEPROM_M24C64.h"


// ============================================================================================
// Variables
static struct {
	uint8_t  Data[30];
	uint32_t Count;
} _Command_Buffer;

static uint32_t _Configuration_Write_Counter;

extern int32_t _Event_Received_Counter[NUM_LED_CHANNELS][NUM_LED_COLORS][2];


// ============================================================================================
// Function Declarations
void Serial_Command_Parse_Command();
void Serial_Command_Send_Configuration_Text(void);
void Serial_Command_Send_Configuration_Hex(void);
void Serial_Command_Return_Ping(void);
void Serial_Command_Write_Configuration_Byte(void);
void Serial_Command_Save_To_EEPROM(void);


/*******************************************************************
    Functions
*******************************************************************/
void Serial_Command_Init()
{
    _Command_Buffer.Count = 0;
    _Configuration_Write_Counter = 0;
}

void Serial_Command_Check_For_Input()
{
    while(USB_Serial_Available())
	{
		uint8_t USB_Data = USB_Serial_Get_Byte();
		if(USB_Data == USB_SERIAL_TERMINATOR)
		{
			Serial_Command_Parse_Command();
		}
		else
		{
			_Command_Buffer.Data[_Command_Buffer.Count++] = USB_Data;
		}
	}
}


/*******************************************************************
    Internal Functions
*******************************************************************/
void Serial_Command_Parse_Command(void)
{
	uint32_t Index, ID, X, Y, Color;
	
	switch (_Command_Buffer.Data[0])
	{
		case 'T':	Serial_Command_Send_Configuration_Text();	break;
		case 'X':	Serial_Command_Send_Configuration_Hex();	break;
		case 'P':	Serial_Command_Return_Ping();				break;
		case 'R':	_Configuration_Write_Counter = 0;	        break;
		case 'W':	Serial_Command_Write_Configuration_Byte();	break;
		// case 'S':	Serial_Save_To_EEPROM();			break;
		case 'd':   Serial_Command_Send_Configuration_Text();   break;

        case 'a':
            for(Color=0;Color < NUM_LED_COLORS; Color++)
            {
                USB_Serial_Send_Int_Dec(_Event_Received_Counter[LED_Channel_1][Color][MIDI_EVENT_NOTE_ON - MIDI_EVENT_NOTE_OFF], 6);
                USB_SERIAL_SEND_STRING(";");
                USB_Serial_Send_Int_Dec(_Event_Received_Counter[LED_Channel_1][Color][MIDI_EVENT_NOTE_OFF - MIDI_EVENT_NOTE_OFF], 6);
                USB_SERIAL_SEND_TERMINATOR();

                _Event_Received_Counter[LED_Channel_1][Color][MIDI_EVENT_NOTE_ON - MIDI_EVENT_NOTE_OFF] = 0;
                _Event_Received_Counter[LED_Channel_1][Color][MIDI_EVENT_NOTE_OFF - MIDI_EVENT_NOTE_OFF] = 0;
            }
            break;

		default:
			USB_SERIAL_SEND_STRING("Unknown Command: ");
			USB_Serial_Put_Char(_Command_Buffer.Data[0]);
			USB_SERIAL_SEND_STRING(" (");
			USB_Serial_Send_Int_Hex(_Command_Buffer.Data[0], 2, true);
			USB_SERIAL_SEND_STRING(")");
			USB_SERIAL_SEND_TERMINATOR();
			break;
	}
	
	_Command_Buffer.Count = 0;
}

void Serial_Command_Send_Configuration_Text(void)
{
    USB_SERIAL_SEND_STRING("Channel MIDI Configuration"); USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  MIDI_Channel:        "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Channel_MIDI_Configuration[0].MIDI_Channel, 2); 			USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Octave:              "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Channel_MIDI_Configuration[0].Octave, 1); 				USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Note Color Red:      "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Channel_MIDI_Configuration[0].Note_Color_Red, 2); 		USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Note Color Green:    "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Channel_MIDI_Configuration[0].Note_Color_Green, 2); 		USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Note Color Blue:     "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Channel_MIDI_Configuration[0].Note_Color_Blue, 2); 		USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Skip Note Off Event: "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Channel_MIDI_Configuration[0].Skip_Note_Off_Event, 1); 	USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Note Reset Enabled:  "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Channel_MIDI_Configuration[0].Note_Reset_Enabled, 1); 	USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Note Reset Timeout:  "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Channel_MIDI_Configuration[0].Note_Reset_Timeout, 3); 	USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_TERMINATOR();
	
	USB_SERIAL_SEND_STRING("Pause Light Configuration"); USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Enabled:    "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Pause_Light_Configuration[0].Enabled, 1); USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Color:      RGB("); 
		USB_Serial_Send_Int_Dec(_EEPROM_Content.Pause_Light_Configuration[0].Color.R, 3); USB_SERIAL_SEND_STRING(", ");
		USB_Serial_Send_Int_Dec(_EEPROM_Content.Pause_Light_Configuration[0].Color.G, 3); USB_SERIAL_SEND_STRING(", ");
		USB_Serial_Send_Int_Dec(_EEPROM_Content.Pause_Light_Configuration[0].Color.B, 3); USB_SERIAL_SEND_STRING(")");
	USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Timeout:    "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Pause_Light_Configuration[0].Timeout, 8); 		USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Reset:      "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Pause_Light_Configuration[0].Reset_Condition, 1); USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Fade Speed: "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Pause_Light_Configuration[0].Fade_Speed, 3); 		USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_TERMINATOR();

	USB_SERIAL_SEND_STRING("Jam Light Configuration"); USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Duration Min:    "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Jam_Light_Configuration.Durations.Min, 5); 			USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Duration Max:    "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Jam_Light_Configuration.Durations.Max, 5); 			USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Hue Angle Start: "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Jam_Light_Configuration.Hue_Angle_Start_Color, 3); 	USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Color Change:    "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Jam_Light_Configuration.Color_Change, 3); 			USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Fade Speed:      "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Jam_Light_Configuration.Fade_Speed, 3); 				USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_TERMINATOR();

	USB_SERIAL_SEND_STRING("Const Light Configuration"); USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Color:      RGB("); 
		USB_Serial_Send_Int_Dec(_EEPROM_Content.Const_Light_Configuration.Color.R, 3); USB_SERIAL_SEND_STRING(", ");
		USB_Serial_Send_Int_Dec(_EEPROM_Content.Const_Light_Configuration.Color.G, 3); USB_SERIAL_SEND_STRING(", ");
		USB_Serial_Send_Int_Dec(_EEPROM_Content.Const_Light_Configuration.Color.B, 3); USB_SERIAL_SEND_STRING(")");
	USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Fade Speed: "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Const_Light_Configuration.Fade_Speed, 3); USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_TERMINATOR();

	USB_SERIAL_SEND_STRING("Device Configuration"); USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Idle Screen:       "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Device_Configuration.Idle_Screen, 1); 				USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Screen Timeout:    "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Device_Configuration.Screen_Timeout, 8); 			USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Rev. Scrolling:    "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Device_Configuration.Reverse_List_Scrolling, 1); 	USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Use Color Corr.:   "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Device_Configuration.Use_Color_Correction, 1); 	USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_STRING("  Current Threshold: "); USB_Serial_Send_Int_Dec(_EEPROM_Content.Device_Configuration.Current_Threshold, 8); 	    USB_SERIAL_SEND_TERMINATOR();
	USB_SERIAL_SEND_TERMINATOR();	
}

void Serial_Command_Send_Configuration_Hex(void)
{
	for(int i=0;i<EEPROM_Get_Content_Size();i++)
	{
		USB_Serial_Send_Int_Hex(*(((uint8_t*)&_EEPROM_Content) + i), 2, false);
	}
	USB_SERIAL_SEND_TERMINATOR();
}

void Serial_Command_Return_Ping(void)
{
	if(_Command_Buffer.Count == 2) {
		USB_Serial_Put_Char(_Command_Buffer.Data[1]);
		USB_SERIAL_SEND_TERMINATOR();
	}
}

void Serial_Command_Write_Configuration_Byte(void)
{
	if(_Command_Buffer.Count != 3) {
		USB_Serial_Put_Char(SERIAL_NACK);
		USB_SERIAL_SEND_TERMINATOR();
		return;
	}

	if(_Configuration_Write_Counter >= EEPROM_Get_Content_Size()) {
		USB_Serial_Put_Char(SERIAL_NACK);
		USB_SERIAL_SEND_TERMINATOR();
		return;
	}

	uint8_t Configuration_Data_Byte = (uint8_t)Convert_CharArray_To_Number(&_Command_Buffer.Data[1], 2);
	*(((uint8_t*)&_EEPROM_Content) + _Configuration_Write_Counter) = Configuration_Data_Byte;

	_Configuration_Write_Counter++;

	USB_Serial_Put_Char(SERIAL_ACK);
	USB_SERIAL_SEND_TERMINATOR();
}

void Serial_Command_Save_To_EEPROM(void)
{
	EEPROM_Trigger_Update();

	USB_Serial_Put_Char(SERIAL_ACK);
	USB_SERIAL_SEND_TERMINATOR();
}

void Display_Start_Buffer_Readout(void)
{
    // cancel_repeating_timer(&_Timer);
    
    // // Send header
    // USB_SERIAL_SEND_STRING("IMGBUF");
    // USB_Serial_Send_Int_Dec(DISPLAY_WIDTH, 4);
    // USB_Serial_Put_Char(',');
    // USB_Serial_Send_Int_Dec(DISPLAY_HEIGHT, 4);
    // USB_Serial_Put_Char(',');
    // USB_Serial_Send_Int_Dec(16, 2);
    // USB_SERIAL_SEND_TERMINATOR();
    
    // uint32_t Pixel_Count = DISPLAY_WIDTH * DISPLAY_HEIGHT;
    
    // for(uint32_t i = 0; i < Pixel_Count; i++)
    // {
    //     Display_Color Pixel = Display_Get_Pixel(i);
    //     USB_Serial_Send_Int_Hex(Pixel, 4, false);
    // }
    // sleep_ms(100);
    // USB_SERIAL_SEND_TERMINATOR();
    
    // add_repeating_timer_ms(40, ISR_Repeating_Timer, NULL, &_Timer);
}