/****************************************************************************
	Aplikace pro indikaci zakladnich stavu zarizeni

*****************************************************************************/
#include "OS.h"
#include "GRAPHICS.h"
#include "Applications.h"
#include "GLCD.h"
#include "stdafx.h"
#include "ImagesStatusBar.h"
#include "Drivers.h"



unsigned char statusBarClockBuff[] = "HH:MM - DD.MM.RR";						//Textovy buffer pro vypis casu
int old_minutes = -1;															//Posledni cas prekresleni-  minuty

FONT statusBarFont = {RGB_RED,FONT_SMALL,RGB_DARK_GRAY};						//Font stavoveho panelu

TScreen StatusBarScreen;														//Obrazovka aplikace
TScreenObject statusBarScreenObjects[STATUS_BAR_OBJECTS_COUNT];					//Objekty obrazovky
TApplicationInternal StatusBarInternal;											//ridici objekt aplikace

TScreenObjectParams statusBarMainShapeParams = {STATUS_BAR_MAIN_SHAPE_WIDTH, STATUS_BAR_MAIN_SHAPE_HEIGHT, &statusBarFont};
TScreenObjectParams statusBarClockParams = {STATUS_BAR_CLOCK_WIDTH, STATUS_BAR_MAIN_SHAPE_HEIGHT, &statusBarFont};

#define CAPTION_LENGTH 20														//Delka stavoveho textu

unsigned char statusBarText[CAPTION_LENGTH+1];									//Text stavoveho panelu

/****************************************************************************
	Odezva tlacitek se sipkami
		TIME_SETUP_XXXX_DOWN,
		TIME_SETUP_XXXX_UP

	Vstup: 
		text:			text stavoveho panelu

	Vystup
		neni

*****************************************************************************/
void StatusBarTextUpdate(unsigned char* text)
{
	if (text == 0)																//pokud neni text k vypisu
	{
		clearBuffer(statusBarText,CAPTION_LENGTH);								//Vymaz buffer
	}
	else
	{
		int len = get_length(text);												//Zjisti delku textu
		for (int i = 0; i < (len > CAPTION_LENGTH? CAPTION_LENGTH:len); i++)	//Pokud ma text vice nez je dovoleno
		{
			statusBarText[i] = text[i];											//Kopiruj to co se vejde
		}
	}
	if (StatusBarInternal.State == STATUS_BAR_ACTIVE)							//pokud je stavovy panel aktivni
		StatusBarScreen.UpdateObject(STATUS_BAR_CAPTION);						//aktualizuj objekt
}


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

	Vstup: 
		msg:				zprava pro aplikaci

	Vystup
		RESULT:				vysledek aplikace

*****************************************************************************/
RESULT SBMsgBox(MESSAGE *msg)
{
	switch (msg->msg)
	{
	case INIT:
		DebugOut("Status bar INIT command received.\n");
		if (StatusBarInternal.State == STATUS_BAR_NOT_INITIALIZED)				//POkud neni aplikace inicializovana
		{
			StatusBarInternal.State = STATUS_BAR_INITIALIZE;					//Priprav ji na inicializaci
			return PASSED;
		}
		break;
	case RUN:
		DebugOut("Status bar RUN command received.\n");
		if (StatusBarInternal.State == STATUS_BAR_READY || StatusBarInternal.State == STATUS_BAR_ACTIVE || StatusBarInternal.State == STATUS_BAR_STOP)	//Pokud je aplikace ve spustitelnem stavu
		{
			StatusBarInternal.State = STATUS_BAR_RESET;							//Preved aplikaci do stavu spousteni
			return PASSED;
		}
		break;
	case STOP:
		DebugOut("Status bar STOP command received.\n");
		if (StatusBarInternal.State > STATUS_BAR_INITIALIZE)					//Pokud je aplikace inicializovana
		{
			StatusBarInternal.State = STATUS_BAR_STOP;							//lze zadat pozadavek na ukonceni
		}
		return PASSED;
		break;
	case GET_STATE:
		return (RESULT)StatusBarInternal.State;									//Vraci stav objektu
		break;
	case APP_CLICK:
		DebugOut("Status Bar click, nothing to do...\n");						//KLiknuti... co s nim...
		return PASSED;
		break;
	case FORCE_REFRESH:
		DebugOut("Status Bar forced to refresh.\n");							//Vynucene prekresleni panelu
		StatusBarInternal.State = STATUS_BAR_REFRESH_FORCED;
		
		return PASSED;
		break;
	default:
		DebugOut("Status bar UNKNOWN command received.\n");
		break;
	}
	DebugOut("Status bar action failed.\n");
	return FAILED;
}


/****************************************************************************
	Kresleni oblasti s hodinami

	Vstup: 
		obj:		instance objektu ktera vola callback
		msg:		parametry kresleni

	Vystup
		neni

*****************************************************************************/
void DrawClockBox(TScreenObject* obj, OBJECT_MESSAGE msg)
{
	DrawTextBoxShape(obj,msg);									//Vykresleni textove oblasti
	LCD_Goto_XY(5,2);											//presun na pozici
	if (currentTime.hours < 10)									//Pokud je mene nez 10 hodin
		LCD_printf((unsigned char*)"0");						//kresli nulu
	LCD_printf((unsigned char*)int2char(currentTime.hours));	//vytiskni cas
	LCD_printf((unsigned char*)":");
	if (currentTime.minutes < 10)
		LCD_printf((unsigned char*)"0");
	LCD_printf((unsigned char*)int2char(currentTime.minutes));
	LCD_printf((unsigned char*)" ");
	if (currentTime.day < 10)
		LCD_printf((unsigned char*)"0");
	LCD_printf((unsigned char*)int2char(currentTime.day));
	LCD_printf((unsigned char*)".");
	if (currentTime.month < 10)
		LCD_printf((unsigned char*)"0");
	LCD_printf((unsigned char*)int2char(currentTime.month));
	LCD_printf((unsigned char*)".");
	LCD_printf((unsigned char*)int2char(currentTime.year));

	old_minutes = currentTime.minutes;
}

/****************************************************************************
	Vykresleni stavu pripojeni

	Vstup: 
		obj:		instance objektu ktera vola callback
		msg:	parametry kresleni

	Vystup
		neni

*****************************************************************************/
void DrawWifiState(TScreenObject* obj, OBJECT_MESSAGE msg)
{
	switch(myConnectionState)
	{
	case CONNECTION_CONNECTED:
		LCD_draw_bitmap_cond(obj->x,obj->y,BMP_wifi_networked,0);			//pripojeno
		break;
	case CONNECTION_DISCONNECTED:
		LCD_draw_bitmap_cond(obj->x,obj->y,BMP_wifi_idle,0);				//odpojeno
		break;
	case CONNECTION_ERROR:
		LCD_draw_bitmap_cond(obj->x,obj->y,BMP_wifi_error,0);				//chyba
		break;
	}
}

/****************************************************************************
	Vypsani textu stavoveho panelu

	Vstup: 
		obj:		instance objektu ktera vola callback
		msg:		parametry kresleni

	Vystup
		neni

*****************************************************************************/
void DrawStatusBarCaption(TScreenObject* obj, OBJECT_MESSAGE msg)
{
	int len = get_length(statusBarText);					//Zjisteni delky textu
	TRect r = {obj->x, obj->y, 60, 15};						//definice obdelniku pro tisk
	LCD_Set_Font(obj->params->font);						//Nastaveni pisma
	LCD_Set_Font_Size(FONT_MINIMAL);
	LCD_Set_ROI(&r);							
	LCD_Goto_XY(obj->x+2,STATUS_BAR_MAIN_SHAPE_TOP+6);		//Nastaveni pozice
	LCD_printf(statusBarText);								//tisk textu
	for (int i = 0; i< CAPTION_LENGTH-len; i++)				//vymazani zbytku popisku
		LCD_putchar(' ');
}

/****************************************************************************
	Vykresleni stavu baterie

	Vstup: 
		obj:		instance objektu ktera vola callback
		msg:		parametry kresleni

	Vystup
		neni

*****************************************************************************/
void DrawBatteryState(TScreenObject* obj, OBJECT_MESSAGE msg)
{
	int val = GetBatteryValue();										//Zjisteni napeti na baterii
	if (val > BATTERY_FULL)												
		LCD_draw_bitmap_cond(obj->x, obj->y, BMP_batt_full,0);			//Baterie je plna
	else if (val > BATTERY_MEDIUM)
		LCD_draw_bitmap_cond(obj->x, obj->y, BMP_batt_medium,0);		//Baterie je stredne nabita
	else if (val > BATTERY_LOW)
		LCD_draw_bitmap_cond(obj->x, obj->y, BMP_batt_low,0);			//Baterie je vybita
	else
	{
		LCD_draw_bitmap_cond(obj->x, obj->y, BMP_batt_critical,0);		//Baterie je kriticky vybita
		DebugOut("Battery state lower than low... Such a scarry state cannot be displayed...\r\n");
	}
}


/****************************************************************************
	Vykresleni typu spojeni

	Vstup: 
		obj:		instance objektu ktera vola callback
		msg:		parametry kresleni

	Vystup
		neni

*****************************************************************************/
void DrawConnectionState(TScreenObject* obj, OBJECT_MESSAGE msg)
{
	char state = TaskGetState(DESKTOP);
	if (state == M_TASK_FAILED || state == M_TASK_READY || state == M_TASK_NOT_INITIALIZED)			//Pokud bezi konzole nebo plocha
	{
		state = TaskGetState(CONSOLE);
		if (state == M_TASK_FAILED || state == M_TASK_READY || state == M_TASK_NOT_INITIALIZED)
			return;
	}
	switch(remoteConnection)
	{
	case OS_WIFI:
		LCD_draw_bitmap_cond(obj->x, obj->y, BMP_wifi,0);											//vykresli obrazek wifi
		break;
	case OS_SERIAL:
		LCD_draw_bitmap_cond(obj->x, obj->y, BMP_cable,0);											//vykresli obrazek serioveho portu
		break;
	}
}

/****************************************************************************
	Vykresleni stavu sifrovani

	Vstup: 
		obj:		instance objektu ktera vola callback
		msg:		parametry kresleni

	Vystup
		neni

*****************************************************************************/
void DrawCipherState(TScreenObject* obj, OBJECT_MESSAGE msg)
{
	char state = TaskGetState(DESKTOP);
	if (state == M_TASK_FAILED || state == M_TASK_READY || state == M_TASK_NOT_INITIALIZED)			//POkud je spustena konzole nebo plocha
	{
		state = TaskGetState(CONSOLE);
		if (state == M_TASK_FAILED || state == M_TASK_READY || state == M_TASK_NOT_INITIALIZED)
			return;
	}
	if (remoteConnection != OS_WIFI)																//POkud neni spustena wifi
		return;
	

	switch (remoteSSL)
	{
	case YES:
		LCD_draw_bitmap_cond(obj->x, obj->y, BMP_lock_closed,0);									//Sifrovani
		break;
	case NO:
		LCD_draw_bitmap_cond(obj->x, obj->y, BMP_lock_open,0);										//nesifrovani
		break;
	}
}

/****************************************************************************
	Vykresleni stavu pripojeni

	Vstup: 
		obj:		instance objektu ktera vola callback
		msg:		parametry kresleni

	Vystup
		neni

*****************************************************************************/
void DrawConnectionType(TScreenObject* obj, OBJECT_MESSAGE msg)
{
	char state = TaskGetState(DESKTOP);
	if (state == M_TASK_FAILED || state == M_TASK_READY || state == M_TASK_NOT_INITIALIZED)					//pokud neni spustena konzole nebo plocha
	{
		state = TaskGetState(CONSOLE);
		if (state == M_TASK_FAILED || state == M_TASK_READY || state == M_TASK_NOT_INITIALIZED)
			return;																							//konec
	}
	switch (remoteConnectionEstablished)	
	{
	case YES:
		LCD_draw_bitmap_cond(obj->x, obj->y, BMP_connected,0);												//Pripojeno
		break;
	case NO:
		LCD_draw_bitmap_cond(obj->x, obj->y, BMP_disconnected,0);											//Nepripojeno
		break;
	}
}

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

	Vstup: 
		neni

	Vystup
		neni

*****************************************************************************/
RESULT StatusBarInitialize(void)
{
	StatusBarScreen.Init(STATUS_BAR_OBJECTS_COUNT,statusBarScreenObjects,&statusBarFont, FALSE);							//Inicializace obrazovky stavoveho panelu
	StatusBarInternal.Init(STATUS_BAR,0,0,STATUS_BAR_MAIN_SHAPE_WIDTH, STATUS_BAR_MAIN_SHAPE_HEIGHT,&StatusBarScreen,0,NO);	//Inicializace ridici struktury
	if (StatusBarInternal.Screen == 0)
	{
		return FAILED;
	}
	/****************************************************************************
	Inicializace objektu...

	*****************************************************************************/
	StatusBarInternal.Screen->objects[STATUS_BAR_MAIN_SHAPE].Init(	STATUS_BAR_MAIN_SHAPE_LEFT,
																	STATUS_BAR_MAIN_SHAPE_TOP,
																	TEXT_AREA,
																	STATUS_BAR_MAIN_SHAPE,
																	0,
																	OBJECT_ENABLED,
																	&statusBarMainShapeParams,
																	0,
																	&DrawTextBoxShape);

	StatusBarInternal.Screen->objects[STATUS_BAR_CLOCK].Init(		STATUS_BAR_MAIN_SHAPE_LEFT,
																	STATUS_BAR_MAIN_SHAPE_TOP,
																	TEXT_AREA,
																	STATUS_BAR_CLOCK,
																	statusBarClockBuff,
																	OBJECT_ENABLED,
																	&statusBarClockParams,
																	0,
																	&DrawClockBox);
	
		StatusBarInternal.Screen->objects[STATUS_BAR_BATTERY].Init(		STATUS_BAR_MAIN_SHAPE_LEFT+STATUS_BAR_MAIN_SHAPE_WIDTH - STATUS_BAR_ICONS_OFFSET,
																	STATUS_BAR_MAIN_SHAPE_TOP + 3,
																	ICON,
																	STATUS_BAR_BATTERY,
																	0,
																	OBJECT_ENABLED,
																	0,
																	0,
																	&DrawBatteryState);

	StatusBarInternal.Screen->objects[STATUS_BAR_WIFI].Init(		STATUS_BAR_MAIN_SHAPE_LEFT+STATUS_BAR_MAIN_SHAPE_WIDTH - (STATUS_BAR_ICONS_OFFSET+20),
																	STATUS_BAR_MAIN_SHAPE_TOP + 3,
																	ICON,
																	STATUS_BAR_WIFI,
																	0,
																	OBJECT_ENABLED,
																	0,
																	0,
																	&DrawWifiState);



		StatusBarInternal.Screen->objects[STATUS_BAR_CONNECTION_TYPE].Init(		STATUS_BAR_MAIN_SHAPE_LEFT+STATUS_BAR_MAIN_SHAPE_WIDTH - (STATUS_BAR_ICONS_OFFSET+40),
																	STATUS_BAR_MAIN_SHAPE_TOP + 3,
																	ICON,
																	STATUS_BAR_CONNECTION_TYPE,
																	0,
																	OBJECT_ENABLED,
																	0,
																	0,
																	&DrawConnectionState);

		StatusBarInternal.Screen->objects[STATUS_BAR_CIPHER_STATE].Init(		STATUS_BAR_MAIN_SHAPE_LEFT+STATUS_BAR_MAIN_SHAPE_WIDTH - (STATUS_BAR_ICONS_OFFSET+60),
																	STATUS_BAR_MAIN_SHAPE_TOP + 3,
																	ICON,
																	STATUS_BAR_CIPHER_STATE,
																	0,
																	OBJECT_ENABLED,
																	0,
																	0,
																	&DrawCipherState);

		StatusBarInternal.Screen->objects[STATUS_BAR_CONNECTION_STATE].Init(	STATUS_BAR_MAIN_SHAPE_LEFT+STATUS_BAR_MAIN_SHAPE_WIDTH - (STATUS_BAR_ICONS_OFFSET+80),
																	STATUS_BAR_MAIN_SHAPE_TOP + 3,
																	ICON,
																	STATUS_BAR_CONNECTION_STATE,
																	0,
																	OBJECT_ENABLED,
																	0,
																	0,
																	&DrawConnectionType);

		StatusBarInternal.Screen->objects[STATUS_BAR_CAPTION].Init(	STATUS_BAR_CLOCK_WIDTH,
																	STATUS_BAR_MAIN_SHAPE_TOP + 3,
																	ICON,
																	STATUS_BAR_CAPTION,
																	0,
																	OBJECT_ENABLED,
																	&statusBarMainShapeParams,
																	0,
																	&DrawStatusBarCaption);
																	
	return PASSED;
}

void AppStatusBar(void)
{

	switch(StatusBarInternal.State)
	{
	case STATUS_BAR_NOT_INITIALIZED:
		break;
	case STATUS_BAR_INITIALIZE:
		StatusBarInitialize();											//Inicializace aplikace
		StatusBarInternal.State = STATUS_BAR_READY;						//Aplikace pripravena na spusteni
		DebugOut("Status bar initialized.\n");
		break;
	case STATUS_BAR_RESET:
		old_minutes = -1;												//Spousteci proces aplikace
		StatusBarInternal.Screen->EnableAllObjects();					//Povoleni vsech objektu panelu
		StatusBarInternal.Startup();									//Provedeni nezbytnych akci
		StatusBarInternal.State = STATUS_BAR_DRAW;						//Vykresleni
		DebugOut("Status bar reset.\n");
		break;
	case STATUS_BAR_DRAW:
		StatusBarInternal.Screen->Draw();								//Vykresleni
		StatusBarInternal.State = STATUS_BAR_ACTIVE;					//Prechod do akrivniho stavu
		StatusBarInternal.Screen->DisableAllObjects();					//Zakazani vsech objektu
		DebugOut("Status bar Draw.\n");
		break;
	case STATUS_BAR_ACTIVE:
		if (old_minutes !=currentTime.minutes)							//Pokud doslo ke zmene casu (preklapnuti minuty)
		{
			StatusBarInternal.Screen->objects[STATUS_BAR_CLOCK].state = OBJECT_ENABLED;	//Povoleni objektu s hodinami
			StatusBarInternal.State = STATUS_BAR_DRAW;									//Prekresleni
			DebugOut("Status bar clock update.\n");
		}
		
		break;
	case STATUS_BAR_READY:
		break;
	case STATUS_BAR_REFRESH_FORCED:
		StatusBarInternal.Screen->EnableAllObjects();					//Vynucene prekresleni
		StatusBarInternal.State = STATUS_BAR_DRAW;
		break;
	case STATUS_BAR_STOP:
		StatusBarInternal.Stop();										//Ukoncovaci akce
		break;
	case STATUS_BAR_ERROR:
		break;
	default:
		DebugOut("Status Bar unknown state, falling to error.");
		StatusBarInternal.State = STATUS_BAR_ERROR;
		break;
	}

}