/*******************************************************************
File: gui.c
Date: 29-September-2025
Author: Peter Spindler
Description: Functions to create a simple grafical user interface (gui)
********************************************************************/

#include "stm32f7xx_hal.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

#include <string.h>
#include "display.h"
#include "touch.h"

TaskHandle_t GUITaskHandle = NULL;

QueueHandle_t GUIQueue;

#define BUTTON_MARGIN_X   20
#define BUTTON_MARGIN_Y   22
#define GUI_BUTTONSIZE  16

typedef struct {
	uint16_t xPos;
	uint16_t yPos;
	uint16_t Width;
	uint16_t Height;
	char Text[16];
	uint8_t Msg;
} GUI_BUTTON_TypeDef;

static uint8_t GUI_ButtonCnt = 0;
static GUI_BUTTON_TypeDef GUI_Button[GUI_BUTTONSIZE];

uint8_t GUI_IsPressed( void )
{
	if( HAL_GPIO_ReadPin( GPIOC,GPIO_PIN_13 ) == 0 ) {
		return 1;
	} else {
		return 0;
	}
}

void GUI_AddButton( uint16_t xPos, uint16_t yPos, char *Text, uint8_t Msg )
{
	uint8_t i;
	i = GUI_ButtonCnt;
	if( i < GUI_BUTTONSIZE ) {
		GUI_Button[i].xPos = xPos;
		GUI_Button[i].yPos = yPos;
		memset(GUI_Button[i].Text, 0, sizeof(GUI_Button[i].Text) );
		strncpy(GUI_Button[i].Text, Text, sizeof(GUI_Button[i].Text) );
		GUI_Button[i].Msg = Msg;
		GUI_Button[i].Width = Display_GetStringWidth(&FontBig,Text)+2*BUTTON_MARGIN_X;
		GUI_Button[i].Height = Display_GetFontCharHeight(&FontBig)+2*BUTTON_MARGIN_Y;
		GUI_ButtonCnt ++;
	}
}

static void GUI_DisplayButton( uint8_t Index, uint8_t State )
{
	GUI_BUTTON_TypeDef *Button = &GUI_Button[Index];
	uint16_t ColorBack;

	if( State == 0 ) {
		ColorBack = LCD_COLOR_BLACK;
	} else {
		ColorBack = LCD_COLOR_BLUE;
	}

	Display_FillRect( Button->xPos,Button->yPos,	Button->Width,Button->Height, ColorBack );
	Display_DrawRect(Button->xPos,Button->yPos,	Button->Width,Button->Height, LCD_COLOR_WHITE );
	Display_PrintString( Button->xPos+BUTTON_MARGIN_X, Button->yPos+BUTTON_MARGIN_Y, LCD_COLOR_WHITE,ColorBack, &FontBig, Button->Text);
}

static void GUI_Task( void *arguments ) {
	uint8_t TouchState = 0;
	uint16_t xTouch, yTouch;
	uint8_t i;
	uint8_t ButtonPressedIndex=0;
	uint8_t Msg;
	uint32_t EventTime;

	for(i=0;i<GUI_ButtonCnt;i++) {
		GUI_DisplayButton(i,0);
	}

	while( 1 ) {
		vTaskDelay(20);
		if( TouchState == 0 && Touch_IsPressed() ) {
			if( Touch_ReadPos( &xTouch, &yTouch ) ) {

				ButtonPressedIndex = 0xff;
				for(i=0;i<GUI_ButtonCnt;i++) {
					if( xTouch >= GUI_Button[i].xPos &&
							xTouch <= GUI_Button[i].xPos + GUI_Button[i].Width &&
							yTouch >= GUI_Button[i].yPos &&
							yTouch <= GUI_Button[i].yPos + GUI_Button[i].Height ) {
						ButtonPressedIndex = i;
					}
				}
				if( ButtonPressedIndex != 0xff ) {
					GUI_DisplayButton(ButtonPressedIndex,1);
					xQueueSendToBack( GUIQueue, ( void * ) &GUI_Button[ButtonPressedIndex].Msg, ( portTickType ) 0 );
					TouchState = 1;
					EventTime = HAL_GetTick() + 500;
				}
			}

		} else if( TouchState == 1 ) {
			if( !Touch_IsPressed() ) {
				if( ButtonPressedIndex != 0xff ) {
					GUI_DisplayButton(ButtonPressedIndex,0);
				}
				TouchState = 0;
			} else if( HAL_GetTick() > EventTime ) {
				if( ButtonPressedIndex != 0xff ) {
					Msg = GUI_Button[ButtonPressedIndex].Msg; // | 0x80;
					xQueueSendToBack( GUIQueue, ( void * ) &Msg, ( portTickType ) 0 );
				}
				EventTime = HAL_GetTick() + 50;
			}
		}

	}
}

void GUI_Init( void ) {
	portENABLE_INTERRUPTS(); // Workaround to re-enable interrupts after FreeRTOS functions
    Touch_Init();
    
	GUIQueue = xQueueCreate( 10, sizeof( uint8_t) );
	xTaskCreate(GUI_Task,"GUI", configMINIMAL_STACK_SIZE,NULL,0,&GUITaskHandle);

	portENABLE_INTERRUPTS(); // Workaround to re-enable interrupts after FreeRTOS functions
}
