/****************************************************************************
	Aplikace specialni klavesnice.

*****************************************************************************/
#ifdef PCSIM
	#include "stdafx.h"
#endif

#include "Applications.h"
#include "GRAPHICS.h"
#include "OS.h"
#include "GLCD.h"

/****************************************************************************
	Globalni definice fontu

*****************************************************************************/
FONT SpecialsScreenFont = {RGB_CYAN,FONT_SMALL,RGB_DARK_GRAY};
FONT SpecialsFSButtonFont = {RGB_RED,FONT_SMALL,RGB_LIGHT_GRAY};

TScreen specialsScreen;																	//Obrazovka aplikace
TScreenObject specialsScreenObjects[SPECIALS_OBJECT_COUNT];								//Objekty aplikace
	
TApplicationInternal SpecialsInternal;													//Ridici objekt aplikace

char FN_FS[][4] = {"F1","F2","F3","F4","F5","F6","F7","F8","F9","F10","F11","F12"};		//definice rozlozeni klavesnice
char FN_OTHERS[][4] = {"CTL","ALT","ESC","DEL","BCK","TAB","HOM","END"} ;
char FN_OTHERS2[][6] = {"ENTER","SPACE"};
char SpecialsResult = -1;
char specKey = 0;
/****************************************************************************
	Parametry objektu

*****************************************************************************/
TScreenObjectParams SpecialsMainShapeParams = {SPECIALS_XC-SPECIALS_XA,SPECIALS_YC-SPECIALS_YA,&SpecialsScreenFont};
TScreenObjectParams SpecialsFSParams = {SPECIALS_FS_BUTTONS_WIDTH, SPECIALS_FS_BUTTONS_HEIGHT, &SpecialsFSButtonFont};
TScreenObjectParams SpecialsFNParams = {SPECIALS_FN_BUTTONS_WIDTH, SPECIALS_FN_BUTTONS_HEIGHT, &SpecialsFSButtonFont};


/****************************************************************************
	Postovni schranka aplikace

	Vstup: 
		msg:			zprava

	Vystup
		neni

*****************************************************************************/
RESULT SPMsgBox(MESSAGE * msg)
{
	POSITION* tmpPosition = 0;
	switch (msg->msg)
	{
	case RUN:
		DebugOut("Specials RUN command received.\n");
		if (SpecialsInternal.State == SPECIALS_READY)					//pokud je aplikace pripravena
		{
			SpecialsResult = -1;										//vynuluj posledni vysledek
			SpecialsInternal.State = SPECIALS_RESTART;					//priprav aplikaci na spusteni
			return PASSED;
		}
		DebugOut("Specials could not be run.\n");
		return FAILED;
			
		break;
	case INIT:
		if (SpecialsInternal.State == SPECIALS_NOT_INITIALIZED)			//Pokud neni aplikace zinicializovana
		{
			DebugOut("Specials INIT command received.\n");
			SpecialsInternal.State = SPECIALS_INITIALIZE;				//Proved inicializaci
			return PASSED;
		}
		break;
	case GET_STATE:
		return (RESULT)SpecialsInternal.State;							//Vraci aktualni stav aplikace
		break;
	case GET_RESULT:
		return (RESULT)SpecialsResult;									//Vraci vysledek aplikace
		break;
	case APP_CLICK:
		SpecialsInternal.ClickPosition.isFresh = YES;					//bylo prijato kliknuti do aplikace
		tmpPosition = (POSITION*)msg->data;								//zkopiruj info o kliknuti
		SpecialsInternal.ClickPosition.x = tmpPosition->x;
		SpecialsInternal.ClickPosition.y = tmpPosition->y;
		DebugOut("Specials click received.\n");
		return PASSED;
		break;
	default:
		break;
		
	}
	return FAILED;
}


/****************************************************************************
	Vykresli hlavni tvar aplikace

	Vstup: 
		obj:			instance objektu
		message:		parametr kresleni

	Vystup
		neni

*****************************************************************************/
void DrawSpecialsTextBox(TScreenObject* obj ,OBJECT_MESSAGE message)
{
	DrawTextBoxShape(obj,message);
	LCD_Goto_XY(obj->x+5,obj->y+5);
	LCD_printf(obj->caption);
}


/****************************************************************************
	Vykresli tlacitko v aplikaci

	Vstup: 
		obj:			instance objektu
		message:		parametr kresleni

	Vystup
		neni

*****************************************************************************/
void DrawSpecialsFS1Button(TScreenObject* obj ,OBJECT_MESSAGE message)
{
	DrawButtonShape(obj,message);
	LCD_Goto_XY(obj->x+(obj->id<FN_F10?8:3), obj->y+8);		//vypocet spravne pozice textu tlacitka
	LCD_printf(obj->caption);
}

/****************************************************************************
	Odezva tlacitek aplikace

	Vstup: 
		obj:			instance objektu
		message:		parametr kresleni

	Vystup
		neni

*****************************************************************************/
void SpecialsFNButtonsCallback(TScreenObject* obj ,OBJECT_MESSAGE message)
{
#ifdef FIX_ALL_WARNINGS
	message;obj;
#endif
	SpecialsResult = obj->id;						//Ulozi se vysledek kliknuti
	SpecialsInternal.State = SPECIALS_STOP;			//Ukonceni aplikace
}

/****************************************************************************
	Odezva tlacitka CTRL

	Vstup: 
		obj:			instance objektu
		message:		parametr kresleni

	Vystup
		neni

*****************************************************************************/
void CTRLCallback(TScreenObject* obj, OBJECT_MESSAGE message)
{
#ifdef FIX_ALL_WARNINGS
	message;obj;
#endif
	SpecialsInternal.RunApplication(KEYBOARD);			//Spustit klavesnici
	specKey = FN_CTRL;									//ulozit nazev spousteciho objektu
}


/****************************************************************************
	Inicializace aplikace

	Vstup: 
		neni

	Vystup
		neni

*****************************************************************************/
RESULT specialsInitialize(void)
{
	specialsScreen.Init(SPECIALS_OBJECT_COUNT,specialsScreenObjects,&SpecialsScreenFont,NO);				//Inicializace okna aplikace
	SpecialsInternal.Init(SPECIALS,SPECIALS_XA,SPECIALS_YA,SPECIALS_XC,SPECIALS_YC,&specialsScreen,0,NO);	//Inicializace ridici struktury
		if (SpecialsInternal.Screen == 0)
		{
			return FAILED;
		}
		
		/****************************************************************************
		Inicializace objektu aplikace. Je vyuzito velke podobnosti tlacitek a tudiz
		i velke podobnosti jejich inicializace

		*****************************************************************************/
		SpecialsInternal.Screen->objects[SPECIALS_MAIN_SHAPE].Init(SPECIALS_XA,SPECIALS_YA,BACKGROUND,SPECIALS_MAIN_SHAPE,STR_FUNCTION_KEYS,OBJECT_ENABLED,&SpecialsMainShapeParams,0,&DrawSpecialsTextBox);
		for (char i = FN_F1; i <= FN_F10;i++)
		{
			SpecialsInternal.Screen->objects[i].Init(SPECIALS_XA+SPECIALS_FS_BUTTONS_LEFT+(i-1)*(SPECIALS_FS_BUTTONS_DISTANCE+SPECIALS_FS_BUTTONS_WIDTH), SPECIALS_YA+SPECIALS_FS_BUTTONS_TOP,BUTTON,i,(unsigned char*)FN_FS[i-1],OBJECT_ENABLED,&SpecialsFSParams,&SpecialsFNButtonsCallback,&DrawSpecialsFS1Button);
		}

		for (char i = FN_F11; i <= FN_F12; i++)
		{
			SpecialsInternal.Screen->objects[i].Init(SPECIALS_XA+SPECIALS_FS_BUTTONS_LEFT+(i-7)*(SPECIALS_FS_BUTTONS_DISTANCE+SPECIALS_FS_BUTTONS_WIDTH), SPECIALS_YA+SPECIALS_FS_BUTTONS_TOP+SPECIALS_FS_BUTTONS_DISTANCE+SPECIALS_FS_BUTTONS_HEIGHT,BUTTON,i,(unsigned char*)FN_FS[i-1],OBJECT_ENABLED,&SpecialsFSParams,&SpecialsFNButtonsCallback,&DrawSpecialsFS1Button);
		}
		
		for (char i = FN_CTRL; i <= FN_END; i++)
		{
			SpecialsInternal.Screen->objects[i].Init(SPECIALS_XA+SPECIALS_FN_BUTTONS_LEFT+(i-FN_CTRL)*(SPECIALS_FN_BUTTONS_DISTANCE+SPECIALS_FN_BUTTONS_WIDTH), SPECIALS_YA+SPECIALS_FN_BUTTONS_TOP,BUTTON,i,(unsigned char*)FN_OTHERS[i-FN_CTRL],OBJECT_ENABLED,&SpecialsFNParams,&SpecialsFNButtonsCallback,&DrawButton);
		}

		SpecialsInternal.Screen->objects[BTN_BACK].Init(SPECIALS_XA+SPECIALS_FN_BUTTONS_LEFT,SPECIALS_YA+SPECIALS_FN_BUTTONS_TOP+SPECIALS_FN_BUTTONS_DISTANCE+SPECIALS_FN_BUTTONS_HEIGHT,BUTTON,BTN_BACK,STR_CANCEL,OBJECT_ENABLED,&PARAMS_BTN_CANCEL,&SpecialsFNButtonsCallback,&DrawButton);
		SpecialsInternal.Screen->objects[FN_ENTER].Init(SPECIALS_XA+190,SPECIALS_YA+SPECIALS_FN_BUTTONS_TOP+SPECIALS_FN_BUTTONS_DISTANCE+SPECIALS_FN_BUTTONS_HEIGHT,BUTTON,FN_ENTER,STR_ENTER,OBJECT_ENABLED,&PARAMS_BTN_OK,&SpecialsFNButtonsCallback,&DrawButton);
		SpecialsInternal.Screen->objects[FN_SPACE].Init(SPECIALS_XA+370,SPECIALS_YA+SPECIALS_FN_BUTTONS_TOP+SPECIALS_FN_BUTTONS_DISTANCE+SPECIALS_FN_BUTTONS_HEIGHT,BUTTON,FN_ENTER,STR_SPACE,OBJECT_ENABLED,&PARAMS_BTN_INFO_OK,&SpecialsFNButtonsCallback,&DrawButton);
		SpecialsInternal.Screen->objects[FN_CTRL].object_callback = CTRLCallback;
	

	return PASSED;
}

/****************************************************************************
	Ridici smycka aplikace

	Vstup: 
		neni

	Vystup
		neni

*****************************************************************************/
void AppSpecials(void)
{
	switch (SpecialsInternal.State)
	{
	case SPECIALS_NOT_INITIALIZED:
		break;
	case SPECIALS_INITIALIZE:
		SpecialsInternal.State = SPECIALS_READY;								//nastavit novy stav aplikace
		if (specialsInitialize() !=PASSED)										//Inicializace aplikace
		{
			DebugOut("Specials could not be initialized. Falling to error.\n");
			SpecialsInternal.State = SPECIALS_FAILED;							//V pripade chyby
			break;
		}
		DebugOut("Specials initialized.\n");
		break;
	case SPECIALS_RESTART:
		SpecialsInternal.Startup();												//Ulohy nezbytne pro spusteni

		SpecialsInternal.State = SPECIALS_DRAW;									//Prechod do dalsiho stavu
		break;
	case SPECIALS_DRAW:
		SpecialsInternal.Screen->Draw();										//Vykresleni
		SpecialsInternal.State = SPECIALS_ACTIVE;								//Prechod do stavu spusteno
		break;
	case SPECIALS_ACTIVE:
		SpecialsInternal.ProceedClick();										//Zpracovani kliknuti
		break;
	case SPECIALS_WAITING:
		switch(SpecialsInternal.TryToResume())									//Cekani na ukonceni spustene aplikace
		{
		case KEYBOARD:
			//Normalizace vysledku
			SpecialsResult = KeyboardBuffer.TextBuffer[0]>='a'?KeyboardBuffer.TextBuffer[0]-'a'+'A':KeyboardBuffer.TextBuffer[0];
			if (specKey == FN_ALT)
			{
				SpecialsResult-='A';					//Pokud je stisknuto ALT, je vysledek kodovan malym pismenem
				SpecialsResult+='a';
			}
			SpecialsInternal.State = SPECIALS_STOP;		//Ukonceni aplikace
			break;
		case NONE:
			break;
		default:
			DebugOut("Returned to Specials from unknown application.\n");
			break;
		}
		break;
	case SPECIALS_READY:
		break;
	case SPECIALS_STOP:
		SpecialsInternal.Stop();						//Ukoncovaci akce
		break;
	case SPECIALS_FAILED:
		break;
	default:
		break;
	}
}