/****************************************************************************
	Aplikace pro spravu sitoveho nastaveni.

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

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

/****************************************************************************
	Makro pro osetreni cekani pri prechodech mezi stavy

*****************************************************************************/
#define NS_WAIT_FOR_FINISH()	if (WifiBusy() == YES)\
                                {\
									LedOn(LED_4);\
									protectStamp = GetTimeStamp();\
									break;\
                                }\
								if (WifiOK() == NO)\
								{\
									LedOff(LED_4);\
									netSetupConnectState = NS_ERROR;\
									myConnectionState = CONNECTION_ERROR;\
									DebugOut("ERROR\r\n");\
									break;\
								}\
                                if (GetElapsedTime(protectStamp) < 100)\
									break;\
                                LedOff(LED_4);\
                                setupHandleStamp = GetTimeStamp();\
								DebugOut("OK\r\n"); 

static TIME_STAMP protectStamp;													//ochranna casova znamka pro oddeleni prikazu a odpovedi
MESSAGE ipMask = {SET_MASK,0};													//Maska IP adresy
char ipLong[] = "NNN.NNN.NNN.NNN/NN ";											//Dlouha maska
char ipShort[] = "NNN.NNN.NNN.NNN ";											//Kratka maska

char maxGetterCounter = 0;							

/****************************************************************************
	Definice fontu aplikace

*****************************************************************************/
FONT netSetupScreenFont = {RGB_GREEN,FONT_SMALL,RGB_DARK_BLUE};
FONT netSetupDivisorFont = {RGB_CYAN,FONT_SMALL,RGB_DARK_GRAY};
FONT netSetupButtonsEnabledFont = {RGB_DARK_GREEN,FONT_SMALL,RGB_LIGHT_GRAY};
FONT netSetupCommonsFont = {RGB_RED,FONT_SMALL,RGB_LIGHT_GRAY};


TScreen netSetupScreen;															//Obrazovka aplikace
TScreenObject netSetupScreenObjects[NET_SETUP_OBJECT_COUNT];					//Objekty aplikace

TApplicationInternal NetSetupInternal;											//Ridici objekt aplikace
unsigned char commandBuffer[30];												//Prikazovy zasobnik


/****************************************************************************
	Definice parametru objektu aplikace

*****************************************************************************/
TScreenObjectParams netSetupDivisorParams = {0, 0, &netSetupDivisorFont};	
TScreenObjectParams netSetupInfoParams = {NET_SETUP_CONTROLS_WIDTH, NET_SETUP_CONTROLS_HEIGHT, &netSetupDivisorFont};
TScreenObjectParams netGlobalsButtonsParams = {NET_SETUP_GLOBALS_BUTTONS_WIDTH, NET_SETUP_GLOBALS_BUTTONS_HEIGHT, &netSetupButtonsEnabledFont};
TScreenObjectParams netGlobalsSmallButtonsParams = {NET_SETUP_GLOBALS_BUTTONS_WIDTH/2, NET_SETUP_GLOBALS_BUTTONS_HEIGHT, &netSetupButtonsEnabledFont};
TScreenObjectParams netGlobalsLongButtonsParams = {NET_SETUP_LOCALS_BUTTONS_WIDTH, NET_SETUP_LOCALS_BUTTONS_HEIGHT, &netSetupButtonsEnabledFont};
TScreenObjectParams netGlobalsCommonButtonsParams = {NET_SETUP_COMMON_BUTTONS_WIDTH, NET_SETUP_COMMON_BUTTONS_HEIGHT, &netSetupCommonsFont};

unsigned char myIP[] = "000.000.000.000";											//Lokalni IP adresa
unsigned char myGateway[] = "000.000.000.000";										//Adresa brany
unsigned char myDNS[] = "000.000.000.000";											//Adresa DNS
unsigned char myMask[] = "32";														//Maska site
unsigned char myPassword[40] = "";													//Heslo site
unsigned char mySSID[NETWORK_NAME_LENGTH] = "";										//Jmeno site
unsigned char myChannel[3];															//Kanal site
SSID_TYPE mySSIDType = SSID_AP;														//Typ site
CIPHER_TYPE myCipher = CIP_NONE;													//Vychozi sifrovani
NET_SETUP_CON_PROC netSetupConnectState = NS_MODULE_START;							//stav ve stavovem automatu rizeni WiFi
TIME_STAMP setupHandleStamp;														//Casova znamka pro rizeni wifi modulu

CONNECTION_STATE myConnectionState = CONNECTION_DISCONNECTED;						//Stav pripojeni
SIGNAL_STRENGTH mySignalStrength = SIGNAL_NONE;										//Sila signalu

ANSWER myAdHoc = NO;																//je-li sit ad-hoc

int NetSetupResult = -1;															//Vysledek ukonceni aplikace

char ipMaxCounterAfterReboot = 0;													//Pocitadlo pro pokus o zotaveni po restartu

static NET_SETUP_OBJECT startingObject = NET_SETUP_NONE;							//Spousteci objekt pro podaplikace


/****************************************************************************
	Vykresleni ramcu v pozadi

	Vstup: 
		obj:			instance objektu
		message:		parametry volani

	Vystup
		neni

*****************************************************************************/
void netSetupDivisorsDraw(TScreenObject* obj ,OBJECT_MESSAGE message)
{
#ifdef FIX_ALL_WARNINGS
	message;
#endif
	//Definice obdelniku
	TRect textAreaRect = {NET_SETUP_GLOBALS_LEFT, NET_SETUP_GLOBALS_TOP, NET_SETUP_GLOBALS_LEFT+NET_SETUP_GLOBALS_WIDTH, NET_SETUP_GLOBALS_TOP+NET_SETUP_GLOBALS_HEIGHT};
	LCD_frect(&textAreaRect,obj->params->font->bg_color);				//pozadi obdelniku
	LCD_rect(&textAreaRect,2,RGB_WHITE);								//ramecek obdelniku
	LCD_Set_Font(obj->params->font);									//Font
	LCD_Goto_XY(NET_SETUP_GLOBALS_LEFT+5,NET_SETUP_GLOBALS_TOP+5);		//Nastaveni pozice
	LCD_Set_ROI(&textAreaRect);											//nastaveni ROI
	LCD_printf(STR_CONNECTION_SETUP);									//tisk textu

	//Definice obdelniku
	TRect localsAreaRectLeft = {NET_SETUP_LOCALS_LEFT,NET_SETUP_LOCALS_TOP, NET_SETUP_LOCALS_LEFT+NET_SETUP_LOCALS_WIDTH, NET_SETUP_LOCALS_TOP+NET_SETUP_LOCALS_HEIGHT};
	LCD_frect(&localsAreaRectLeft,obj->params->font->bg_color);			//Plny obdelnik
	LCD_rect(&localsAreaRectLeft,2,RGB_WHITE);							//ramecek
	LCD_Set_Font(obj->params->font);									//nastaveni fontu
	LCD_Goto_XY(NET_SETUP_LOCALS_LEFT+5,NET_SETUP_LOCALS_TOP+5);		//nastaveni pozice tisku
	LCD_Set_ROI(&localsAreaRectLeft);									//nastaveni ROI
	LCD_printf(STR_IP_SETUP);											//tisk textu
}

/****************************************************************************
	Kreslici funkce informacniho obdelniku

	Vstup: 
		obj:			instance objektu
		message:		parametry kresleni

	Vystup
		neni

*****************************************************************************/
void netSetupInfoDraw(TScreenObject* obj ,OBJECT_MESSAGE message)
{
#ifdef FIX_ALL_WARNINGS
	message;
#endif
	//Definice obdelniku
	TRect controlsAreaRectLeft = {NET_SETUP_CONTROLS_LEFT,NET_SETUP_CONTROLS_TOP, NET_SETUP_CONTROLS_LEFT+NET_SETUP_CONTROLS_WIDTH, NET_SETUP_CONTROLS_TOP+NET_SETUP_CONTROLS_HEIGHT};
	LCD_frect(&controlsAreaRectLeft,obj->params->font->bg_color);							//Vykresleni pozadi
	LCD_rect(&controlsAreaRectLeft,2,RGB_WHITE);											//Vykresleni ramecku
	LCD_Goto_XY(NET_SETUP_CONTROLS_LEFT+5,NET_SETUP_CONTROLS_TOP+5);						//Nastaveni pozicepro tisk
	LCD_Set_ROI(&controlsAreaRectLeft);														//Nastaveni ROI
	LCD_Set_Font(obj->params->font);														//Nastaveni fontu
	LCD_printf(STR_INFO);																	//Tisk nadpisu
	LCD_Goto_XY(NET_SETUP_CONTROLS_LEFT+5,NET_SETUP_CONTROLS_TOP+20);						//Nastaveni pozice pro tisk
	LCD_Set_Font_Size(FONT_MINIMAL);														//Nastaveni velikosti pisma
	LCD_printf(STR_CONNECTION_STATE);														//Stav pripojeni - nadpis
	LCD_Set_Font(obj->params->font);														//Nastaveni fontu
	LCD_Goto_XY(NET_SETUP_CONTROLS_LEFT+5,NET_SETUP_CONTROLS_TOP+40);						//Nastaveni pozice pro tisk

	//POdle stavu pripojeni je volena barva pisma a nasledne tisknut odpovidajici text
	switch(myConnectionState)
	{
	case CONNECTION_ERROR:
	case CONNECTION_UNKNOWN:
		LCD_Set_Font_Color(RGB_RED);
		LCD_printf(STR_CONNECTION_ERROR);
		break;
	case CONNECTION_DISCONNECTED:
		LCD_Set_Font_Color(RGB_DARK_BLUE);
		LCD_printf(STR_CONNECTION_DISCONNECTED);
		break;
	case CONNECTION_CONNECTING:
		LCD_Set_Font_Color(RGB_ORANGE);
		LCD_printf(STR_CONNECTION_CONNECTING);
		break;
	case CONNECTION_CONFIGURING:
		LCD_Set_Font_Color(RGB_BROWN);
		LCD_printf(STR_CONNECTION_CONFIGURING);
		break;
	case CONNECTION_CONNECTED:
		LCD_Set_Font_Color(RGB_GREEN);
		LCD_printf(STR_CONNECTION_CONNECTED);
		break;
	default:
		myConnectionState = CONNECTION_UNKNOWN;
		LCD_Set_Font_Color(RGB_RED);
		LCD_printf(STR_CONNECTION_ERROR);
		break;
	}

	LCD_Goto_XY(NET_SETUP_CONTROLS_LEFT+5,NET_SETUP_CONTROLS_TOP+55);				//Presun pro tisk na pozici
	LCD_Set_Font(obj->params->font);												//Nastaveni fontu
	LCD_Set_Font_Size(FONT_MINIMAL);												//Nastaveni velikosti
	LCD_printf(STR_CONNECTION_SIGNAL_STRENGTH);										//tisk nadpisu
	LCD_Goto_XY(NET_SETUP_CONTROLS_LEFT+5,NET_SETUP_CONTROLS_TOP+74);				//presun na pozici
	LCD_Set_Font(obj->params->font);												//Nastaveni fontu
	
	//podle sily signalu je zvolena barva pisma a nasledne vytisknut prislusny text
	switch(mySignalStrength)
	{
	case SIGNAL_NONE:
		LCD_Set_Font_Color(RGB_BLACK);
		LCD_printf(STR_CONNECTION_SIGNAL_NONE);
		break;
	case SIGNAL_WEAK:
		LCD_Set_Font_Color(RGB_RED);
		LCD_printf(STR_CONNECTION_SIGNAL_WEAK);
		break;
	case SIGNAL_GOOD:
		LCD_Set_Font_Color(RGB_ORANGE);
		LCD_printf(STR_CONNECTION_SIGNAL_GOOD);
		break;
	case SIGNAL_BEST:
		LCD_Set_Font_Color(RGB_GREEN);
		LCD_printf(STR_CONNECTION_SIGNAL_WONDERFUL);
		break;
	}
}

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

	Vstup: 
		msg:			zprava pro aplikaci

	Vystup
		RESULT:			vysledek zpracovani zpravy

*****************************************************************************/
RESULT NSMsgBox(MESSAGE * msg)
{
	POSITION* tmpPosition = 0;
	switch (msg->msg)
	{
	case RUN:
		DebugOut("NetSetup RUN command received.\n");
		if (NetSetupInternal.State == NET_SETUP_READY)							//Pokud je aplikace zinicializovana
		{
			NetSetupResult = -1;												//Vynulovat info o poslednim skonceni
			NetSetupInternal.State = NET_SETUP_RESTART;							//Pripravit ke startu
            maxGetterCounter = 0;												//Pocitadlo pokusu o ziskani IP adresy ze zarizeni
            ipMaxCounterAfterReboot = 0;										//POcitadlo pokusu o zotaveni po restartu
			return PASSED;
		}
		DebugOut("NetSetup could not be run.\n");

		return FAILED;
			
		break;
	case INIT:
		if (NetSetupInternal.State == NET_SETUP_NOT_INITIALIZED)				//Pokud neni aplikace zinicializovana
		{
			DebugOut("NetSetup INIT command received.\n");
			NetSetupInternal.State = NET_SETUP_INITIALIZE;						//Pozadavek na inicializaci
			return PASSED;
		}
		break;
	case GET_STATE:
		return (RESULT)NetSetupInternal.State;									//Vraci stav aplikace
		break;
	case GET_RESULT:
		return (RESULT)NetSetupResult;											//Vraci vysledek po navratu aplikace
		break;
	case APP_CLICK:
		NetSetupInternal.ClickPosition.isFresh = YES;							//POkud je prijato kliknuti
		tmpPosition = (POSITION*)msg->data;										//zkopiruj data kliknuti
		NetSetupInternal.ClickPosition.x = tmpPosition->x;
		NetSetupInternal.ClickPosition.y = tmpPosition->y;
		DebugOut("NetSetup click received.\n");
		return PASSED;
		break;
	default:
		break;
		
	}
	return FAILED;
}


/****************************************************************************
	FUnkce reakce konfiguracniho tlacitka IP adresy

	Vstup: 
		obj:			instance objektu
		message:		parametr volani

	Vystup
		neni

*****************************************************************************/
void netSetupIPConfigCallback(TScreenObject* obj ,OBJECT_MESSAGE message)
{	
#ifdef FIX_ALL_WARNINGS
	message;
#endif
	if (myConnectionState != CONNECTION_CONNECTED)
			return;
	if (obj->id == NET_SETUP_IP)							//Pokud nastavujeme IP ardesu zarizeni
		ipMask.data = ipLong;								//maska je dlouha
	else
		ipMask.data = ipShort;								//jinak kratka
	
	//poslat klavesnici konfiguracni data pro nastaveni masky a numericky rezim
	if (SendTaskMessage(KEYBOARD,&ipMask) == FAILED || SendTaskMessage(KEYBOARD,&DEFAULT_MSG_NUMERIC_ONLY) == FAILED)
	{
		DebugOut("Keyboard configuration failed.\n");
		return;		
	}
	else
	{
		startingObject = (NET_SETUP_OBJECT) obj->id;	//pokud se konfigurace podarila
		NetSetupInternal.RunApplication(KEYBOARD);		//spust klavesnici
	}
}


/****************************************************************************
	Volba ad-hoc/ap spojeni

	Vstup: 
		obj:			instance objektu
		message:		parametr volani

	Vystup
		neni

*****************************************************************************/
void netSetupAdHocCallback(TScreenObject* obj ,OBJECT_MESSAGE message)
{
	if (myAdHoc == NO)
		myAdHoc = YES;
	else
		myAdHoc = NO;
	obj->draw(obj,message);
}


/****************************************************************************
	Reakce tlacitka s nazvem site.

	Vstup: 
		obj:			instance objektu
		message:		parametr volani

	Vystup
		neni

*****************************************************************************/
void netSetupSSIDCallback(TScreenObject* obj ,OBJECT_MESSAGE message)
{
#ifdef FIX_ALL_WARNINGS
	message;
#endif
	startingObject = (NET_SETUP_OBJECT) obj->id;		//Uloz ID startovaciho objektu
	NetSetupInternal.RunApplication(NETWORK_NAMES);		//Spust aplikaci pro ziskani okolnich siti
}

/****************************************************************************
	FUnkce reakce konfiguracniho tlacitka hesla

	Vstup: 
		obj:			instance objektu
		message:		parametr volani

	Vystup
		neni

*****************************************************************************/
void netSetupPasswordCallback(TScreenObject* obj ,OBJECT_MESSAGE message)
{
#ifdef FIX_ALL_WARNINGS
	message;
#endif
	startingObject = (NET_SETUP_OBJECT) obj->id;			//Uloz ID volajiciho objektu
	NetSetupInternal.RunApplication(KEYBOARD);				//Spust klavesnici
}

/****************************************************************************
	Kreslici funkce ukoncovaciho tlacitka

	Vstup: 
		obj:			instance objektu
		message:		parametr volani

	Vystup
		neni

*****************************************************************************/
void netSetupCommonButtonsDraw(TScreenObject* obj ,OBJECT_MESSAGE message)
{
	DrawButtonShape(obj,message);					//vykresli tvar
	LCD_Goto_XY(obj->x+37, obj->y+10);
	LCD_printf(obj->caption);						//vytiskni nazev

}


/****************************************************************************
	Funkce pro kresleni datovych tlacitek

	Vstup: 
		obj:			instance objektu
		message:		parametr volani

	Vystup
		neni

*****************************************************************************/
void netSetupDataFieldsDraw(TScreenObject* obj ,OBJECT_MESSAGE message)
{
	DrawDataButtonSkelet(obj,message);						//kresleni tvaru tlacitka

	//Podle ID tlacitka presun na prislusnou pozici a nasledny tisk textu
	switch(obj->id)
	{
	case NET_SETUP_SSID:
		LCD_printf((unsigned char*)mySSID);			
		break;
	case NET_SETUP_PASSWORD:
		LCD_printf((unsigned char*)"**********");
		break;
	case NET_SETUP_TYPE:
		LCD_Goto_XY(obj->x+22,obj->y+18);
		LCD_printf(myAdHoc == NO? STR_NO:STR_YES);
		break;
	case NET_SETUP_IP:
		//Pokud je sit pripoena, umoznit nastaveni IP adresy (jinak jsou tlacitka zasedla)
		if (myConnectionState != CONNECTION_CONNECTED && myConnectionState != CONNECTION_CONFIGURING)
			LCD_Set_Font_Color(RGB_DARK_GRAY);
		LCD_Goto_XY(obj->x+15,obj->y+18);
		LCD_printf(myIP);
		LCD_printf((unsigned char*)"/");
		LCD_printf(myMask);
		break;
	case NET_SETUP_GATEWAY:
		//Pokud je sit pripoena, umoznit nastaveni IP adresy (jinak jsou tlacitka zasedla)
		if (myConnectionState != CONNECTION_CONNECTED && myConnectionState != CONNECTION_CONFIGURING)
			LCD_Set_Font_Color(RGB_DARK_GRAY);
		LCD_Goto_XY(obj->x+15,obj->y+18);
		LCD_printf(myGateway);
		break;
	case NET_SETUP_DNS:
		//Pokud je sit pripoena, umoznit nastaveni IP adresy (jinak jsou tlacitka zasedla)
		if (myConnectionState != CONNECTION_CONNECTED && myConnectionState != CONNECTION_CONFIGURING)
			LCD_Set_Font_Color(RGB_DARK_GRAY);
		LCD_Goto_XY(obj->x+15,obj->y+18);
		LCD_printf(myDNS);
		break;
	default:
		break;
	}
}


/****************************************************************************
	Funkce reakce tlacitka Zpet

	Vstup: 
		obj:			instance objektu
		message:		parametr volani

	Vystup
		neni

*****************************************************************************/
void netSetupBackCallback(TScreenObject* obj ,OBJECT_MESSAGE message)
{
#ifdef FIX_ALL_WARNINGS
	message;obj;
#endif
	NetSetupInternal.State = NET_SETUP_STOP;			//Ukonci aplikaci
}


/****************************************************************************
	Inicializacni funkce aplikace

	Vstup: 
		neni

	Vystup
		RESULT:			Vysledek inicializace

*****************************************************************************/
RESULT netSetupInitialize(void)
{
	netSetupScreen.Init(NET_SETUP_OBJECT_COUNT,netSetupScreenObjects,&netSetupScreenFont);							//Inicializace obrazovky
	NetSetupInternal.Init(NET_SETUP,NET_SETUP_XA,NET_SETUP_YA,NET_SETUP_XC,NET_SETUP_YC,&netSetupScreen,0,YES);		//Inicializace ridici struktury
		if (NetSetupInternal.Screen == 0)
			return FAILED;
		/****************************************************************************
			Inicializace objektu

		*****************************************************************************/
		NetSetupInternal.Screen->objects[NET_SETUP_DIVISORS].Init(	0,
															0,
															TEXT_BOX,
															NET_SETUP_DIVISORS,
															0,OBJECT_ENABLED,
															&netSetupDivisorParams,
															0,
															&netSetupDivisorsDraw);

		NetSetupInternal.Screen->objects[NET_SETUP_SSID].Init(		NET_SETUP_GLOBALS_BUTTONS_LEFT+NET_SETUP_GLOBALS_LEFT,
															NET_SETUP_GLOBALS_BUTTONS_TOP+NET_SETUP_GLOBALS_TOP,
															BUTTON,NET_SETUP_SSID,
															(unsigned char*)"SSID:",
															OBJECT_ENABLED,
															&netGlobalsButtonsParams,
															netSetupSSIDCallback,
															&netSetupDataFieldsDraw);

		NetSetupInternal.Screen->objects[NET_SETUP_PASSWORD].Init(	NET_SETUP_GLOBALS_BUTTONS_LEFT+NET_SETUP_GLOBALS_BUTTONS_WIDTH+NET_SETUP_GLOBALS_BUTTONS_DISTANCE+NET_SETUP_GLOBALS_LEFT,
															NET_SETUP_GLOBALS_BUTTONS_TOP+NET_SETUP_GLOBALS_TOP,
															BUTTON,NET_SETUP_PASSWORD,
															STR_PASSWORD,
															OBJECT_ENABLED,
															&netGlobalsButtonsParams,
															netSetupPasswordCallback,
															&netSetupDataFieldsDraw);

		NetSetupInternal.Screen->objects[NET_SETUP_TYPE].Init(		NET_SETUP_GLOBALS_BUTTONS_LEFT+(NET_SETUP_GLOBALS_BUTTONS_WIDTH+NET_SETUP_GLOBALS_BUTTONS_DISTANCE)*2+NET_SETUP_GLOBALS_LEFT,
															NET_SETUP_GLOBALS_BUTTONS_TOP+NET_SETUP_GLOBALS_TOP,
															BUTTON,
															NET_SETUP_TYPE,
															STR_ACCESS_TYPE,
															OBJECT_DISABLED,
															&netGlobalsSmallButtonsParams,
															netSetupAdHocCallback,
															&netSetupDataFieldsDraw);

		NetSetupInternal.Screen->objects[NET_SETUP_IP].Init(		NET_SETUP_LOCALS_BUTTONS_LEFT+NET_SETUP_LOCALS_LEFT,
															NET_SETUP_LOCALS_BUTTONS_TOP+NET_SETUP_LOCALS_TOP,
															BUTTON,
															NET_SETUP_IP,
															STR_IP_ADDRESS,
															OBJECT_ENABLED,
															&netGlobalsLongButtonsParams,
															&netSetupIPConfigCallback,
															&netSetupDataFieldsDraw);

		NetSetupInternal.Screen->objects[NET_SETUP_GATEWAY].Init(	NET_SETUP_LOCALS_BUTTONS_LEFT+NET_SETUP_LOCALS_LEFT,
															NET_SETUP_LOCALS_BUTTONS_TOP+NET_SETUP_LOCALS_TOP+NET_SETUP_LOCALS_BUTTONS_HEIGHT+NET_SETUP_LOCALS_BUTTONS_DISTANCE,
															BUTTON,
															NET_SETUP_GATEWAY,
															STR_IP_GATEWAY,
															OBJECT_ENABLED,
															&netGlobalsLongButtonsParams,
															&netSetupIPConfigCallback,
															&netSetupDataFieldsDraw);

		NetSetupInternal.Screen->objects[NET_SETUP_DNS].Init(		NET_SETUP_LOCALS_BUTTONS_LEFT+NET_SETUP_LOCALS_LEFT,
															NET_SETUP_LOCALS_BUTTONS_TOP+NET_SETUP_LOCALS_TOP+(NET_SETUP_LOCALS_BUTTONS_HEIGHT+NET_SETUP_LOCALS_BUTTONS_DISTANCE)*2,
															BUTTON,
															NET_SETUP_DNS,
															STR_IP_DNS,
															OBJECT_ENABLED,
															&netGlobalsLongButtonsParams,
															&netSetupIPConfigCallback,
															&netSetupDataFieldsDraw);

		NetSetupInternal.Screen->objects[NET_SETUP_BACK].Init(		NET_SETUP_COMMON_BUTTONS_LEFT, 
															NET_SETUP_COMMON_BUTTONS_TOP,
															BUTTON,
															NET_SETUP_BACK,
															STR_EXIT,
															OBJECT_ENABLED,
															&netGlobalsCommonButtonsParams,
															&netSetupBackCallback,
															&netSetupCommonButtonsDraw);

		NetSetupInternal.Screen->objects[NET_SETUP_INFO].Init(		NET_SETUP_CONTROLS_LEFT, 
															NET_SETUP_CONTROLS_TOP ,
															TEXT_BOX,NET_SETUP_INFO,
															STR_INFO,
															OBJECT_ENABLED,
															&netSetupInfoParams,
															0,
															&netSetupInfoDraw);

	return PASSED;
}

/****************************************************************************
	Stavovy automat pro rizeni wifi aplikaci

	Vstup: 
		neni

	Vystup
		neni

*****************************************************************************/
void NSHandleConnection(void)
{   
        int i = 0;
	static TIME_STAMP waiter = 0;
	switch(netSetupConnectState)
	{
	case NS_MODULE_START:
		DebugOut("Starting module..."); 
        setupHandleStamp = GetTimeStamp();							//ziskani casove znamky
		myConnectionState = CONNECTION_DISCONNECTED;				//nastaveni stavu Nepripojeno
		WifiSendCommand(DRV_WIFI_TEST);								//Odeslani testovaciho prikazu
		netSetupConnectState = NS_TEST_RECENT;						//Prechod do dalsiho stavu
		break;
	case NS_TEST_RECENT:
		NS_WAIT_FOR_FINISH();										//Cekani na dokonceni
		DebugOut("Getting old configuration...");
		WifiSendCommand(DRV_WIFI_GET_RECENT);						//Odeslani prikazu pro ziskani aktualniho stavu pripojeni
		netSetupConnectState = NS_GET_NETWORK_NAME;					//Prechod do dalsiho stavu
		break;
	case NS_GET_NETWORK_NAME:
		NS_WAIT_FOR_FINISH();										//Cekani na dokonceni

		if (wifiBuffer[0] == 'I' && wifiBuffer[1] == '/')			//POkud prijata data obsahuji pouze I/OK
		{
			netSetupConnectState = NS_IDLE;							//Sit neni pripojena
			myConnectionState = CONNECTION_DISCONNECTED;			//Prechod do Idle stavu
		}
		else
		{
			char i = 0;												//Jinak preparujeme informace o pripojeni
			while(wifiBuffer[i] != ',')								//SSID
			{
				mySSID[i] = wifiBuffer[i];
				i++;
			}
			myConnectionState = CONNECTION_CONFIGURING;				//Prechod do dalsiho stavu
			mySignalStrength = SIGNAL_BEST;							//Nastaveni urovne signalu /TODO: tohle by chtelo opravit
			netSetupConnectState = NS_AFTER_REBOOT2;				//Prechod do stavu po restartu
			NetSetupInternal.Screen->UpdateObject(NET_SETUP_INFO);	//Aktualizace objektu
			NetSetupInternal.Screen->UpdateObject(NET_SETUP_SSID);
			break;
		}
		break;
	case NS_IDLE:
         //Stav kdy se nic nedela, cekame na prikazy       
		break;
	case NS_CLEAR:
        LedOn(LED_4);
		WifiSendCommand(DRV_WIFI_TEST);								//TEst stavu pripojeni
        setupHandleStamp = GetTimeStamp();							//Ziskani casove znamky
		netSetupConnectState = NS_RESET;							//Prechod do dalsiho stavu
		myConnectionState = CONNECTION_CONNECTING;					//Zmena stavu pripojeni na "Pripojuji"
		NetSetupInternal.Screen->UpdateObject(NET_SETUP_INFO);		//Aktualizace objektu
		DebugOut("Testing connection...");
		break;
	case NS_COMMUNICATING:
		NS_WAIT_FOR_FINISH();										//Cekani na vyrizeni prikazu
		netSetupConnectState = NS_RESET;							
		WifiSendCommand(DRV_WIFI_RESET);
		DebugOut("Module reset...");
		break;
	case NS_RESET:
		NS_WAIT_FOR_FINISH();										//Cekani na vyrizeni prikazu
		netSetupConnectState = NS_LOAD_CA;							//Prechod do dalsiho stavu	
		WifiSendCommand(DRV_WIFI_CA_CERT);							//Odelsani certifikatu CA
		DebugOut("Loading CA certificate...");
		break;
	case NS_LOAD_CA:
		NS_WAIT_FOR_FINISH();										//Cekani na dokonceni
		netSetupConnectState = NS_LOAD_CERT;						//Prechod na dalsi stav
		WifiSendCommand(DRV_WIFI_MY_CERT);							//Odeslani certifikatu zarizeni
		DebugOut("Loading device certificate...");
		break;
	case NS_LOAD_CERT:
		NS_WAIT_FOR_FINISH();										//Cekani na dokonceni
		netSetupConnectState = NS_LOAD_PKEY;						//Prechod na dalsi stav
		WifiSendCommand(DRV_WIFI_MY_PKEY);							//Odeslani klice
		DebugOut("Loading PKEY...");
		break;
	case NS_LOAD_PKEY:
		NS_WAIT_FOR_FINISH();										//Cekani na dokonceni
		netSetupConnectState = NS_INTERFACE;						//Prechod do dalsiho stavu
		WifiSendCommand(DRV_WIFI_INTERFACE);						//Nastaveni komunikacniho rozhrani
		DebugOut("Setting interface...");
		break;
	case NS_INTERFACE:
		NS_WAIT_FOR_FINISH();										//Cekani na dokonceni
		netSetupConnectState = NS_BAUDRATE;							//Prechod na dalsi stav
		WifiSendCommand(DRV_WIFI_BAUDRATE);							//Odeslani prikazu na nastaveni komunikacni rychlosti					
		DebugOut("Setting baudrate...");
		break;
	case NS_BAUDRATE:
		NS_WAIT_FOR_FINISH();										//Cekani na dokonceni
		netSetupConnectState = NS_CHANNEL;							//prechod na dalsi stav
		strcopy(DRV_WIFI_CHANNEL_start,commandBuffer);				//sestaveni prikazu
		if (mySSIDType == SSID_AP)									//volba AP/ad-hoc
			str_append(commandBuffer,(unsigned char*)"0");
		else
			str_append(commandBuffer,myChannel);
		str_append(commandBuffer,DRV_LINEEND);						//Ukonceni prikazu
		WifiSendCommand(commandBuffer);								//Odeslani prikazu
		break;
	case NS_CHANNEL:
		NS_WAIT_FOR_FINISH();										//Cekani na dokonceni
		netSetupConnectState = NS_SSID;								//prechod na dalsi stav
		strcopy(DRV_WIFI_SSID_start,commandBuffer);					//sestaveni prikazu
		if (mySSIDType == SSID_ADHOC)								//Pokud je ad-hoc, pridej pred nazev site !
			str_append(commandBuffer,(unsigned char*)"!");
		str_append(commandBuffer,mySSID);							
		str_append(commandBuffer,DRV_LINEEND);
		WifiSendCommand(commandBuffer);								//Odeslani prikazu
		DebugOut("Setting SSID...");
		break;
	case NS_SSID:
		NS_WAIT_FOR_FINISH();										//cekani na dokonceni								
        if (myCipher == 0)
			netSetupConnectState = NS_KEY;
		else
			netSetupConnectState = NS_CIPHER;
		strcopy(DRV_WIFI_CIPHER_TYPE_start,commandBuffer);			//Sestaveni prikazu
		str_append(commandBuffer,(unsigned char*)int2char(myCipher));
		str_append(commandBuffer,DRV_LINEEND);
		WifiSendCommand(commandBuffer);								//Odeslani
		DebugOut("Setting password type...");
		break;
	case NS_CIPHER:
		NS_WAIT_FOR_FINISH();										//Cekani na dokonceni
		netSetupConnectState = NS_KEY;								//Prechod do dalsiho stavu
		if (myCipher == CIP_WPA || myCipher == CIP_WPA2)			//volba prikazu podle sifrovani
		{
			strcopy(DRV_WIFI_WPA_start,commandBuffer);
		}
		else
		{
			strcopy(DRV_WIFI_WEP_start,commandBuffer);
		}
		str_append(commandBuffer,myPassword);						//Sestaveni stringu s heslem
		str_append(commandBuffer,DRV_LINEEND);						
		WifiSendCommand(commandBuffer);								//Odeslani prikazu
		DebugOut("Setting password...");
		break;
	case NS_KEY:
		NS_WAIT_FOR_FINISH();										//Cekani na dokonceni
		netSetupConnectState = NS_REBOOT;							//Prechod do dalsiho stavu
		myConnectionState = CONNECTION_CONFIGURING;					//vystaveni stavu pripojeni na displej
		NetSetupInternal.Screen->UpdateObject(NET_SETUP_INFO);		//Aktualizace objektu
		WifiSendCommand(DRV_WIFI_REBOOT);							//Odelsani prikazu
		DebugOut("Reseting to save configuration...");
		break;
	case NS_REBOOT:
		NS_WAIT_FOR_FINISH();										//cekani na dokonceni
		netSetupConnectState = NS_AFTER_REBOOT;						//Prechod do dalsiho stavu
		DebugOut("CONNECTED!\r\n");
		DebugOut("Re-establishing connection...");
		//WifiSendCommand(DRV_LINEEND);
		break;
	case NS_AFTER_REBOOT:
		if (WifiOnline() != NO && WifiOK() == NO && WifiError() == NO)	//Cekani na dokonceni prikazu
        {
			break;                     
        }
			
        setupHandleStamp = GetTimeStamp();							//Ziskani casove znamky
		waiter = GetTimeStamp();									//ziskani casove znamky
		netSetupConnectState = NS_AFTER_REBOOT2;					//Prechod do dalsiho stavu
		break;
	case NS_AFTER_REBOOT2:
		if (GetElapsedTime(waiter) < 5000)							//Cekani na ustaleni
			break;
		setupHandleStamp = GetTimeStamp();							//Ziskani casove znamky
		DebugOut("OK\r\n");
		DebugOut("Getting IP...");
		WifiSendCommand(DRV_WIFI_GET_IP);							//Odeslani prikazu pro ziskani IP
		netSetupConnectState = NS_GET_IP;
		break;
	case NS_GET_IP:
		if (WifiBusy() == YES)										//Cekani na dokonceni
			break;
		if (WifiOK() == NO)											//KOntrola bezchybneho stavu
		{
			if (ipMaxCounterAfterReboot < 2)						//Pocitadlo pro restart
			{
				netSetupConnectState = NS_AFTER_REBOOT2;			//Opakovani pokusu
				break;
			}
			netSetupConnectState = NS_ERROR;						//Selhani
            myConnectionState = CONNECTION_ERROR;					//vystaveni chyboveho stavu
			DebugOut("ERROR\r\n");
			break;
		}
                setupHandleStamp = GetTimeStamp();					//ziskani casove znamky
                DebugOut("OK\r\n"); 

		{
			//Rozparsovani IP daresy
			char i = 0;
			char found = 0;
			char offset = 0;
			while(((found == 0 || wifiBuffer[i]!='\r')) && i <= 25 )
			{
				if (found == 0 && IS_NUMBER(wifiBuffer[i]))
					found = 1;
				if (found == 1)
				{
					myIP[offset++] = wifiBuffer[i];
				}
				i++;
			}
			myIP[offset] = 0;
			netSetupConnectState = NS_GET_MASK;

			NetSetupInternal.Screen->UpdateObject(NET_SETUP_IP);
		}
		DebugOut("Getting subnet mask...");
		WifiSendCommand(DRV_WIFI_GET_MASK);								//Prikaz k ziskani masky
		break;
	case NS_GET_MASK:
		NS_WAIT_FOR_FINISH();											//Cekani na dokonceni
		{
			int cntr = 0;
			int offset = 0;
			char buff[10] = "";
			unsigned char num = 0;
			char mask = 0;

			//Rozparsovani masky podsite
			for (int i = 0; i < 4; i++)
			{
				while(IS_NUMBER(wifiBuffer[cntr]))
				{
					buff[offset++] = wifiBuffer[cntr];
					cntr++;
				}
				cntr++;
				buff[offset] = 0;
				num = (unsigned char)char2int(buff);
				offset = 0;
				if (num == 255)
				{
					mask += 8;
					continue;
				}
				else
				{
					while(num > 0)
					{
						mask++;
						num = num<<2;
					}
					break;
				}	
	
			}
			if (mask < 32)
			{
				strcopy((unsigned char*)int2char(mask),myMask);			//Pokud je maska platna
				NetSetupInternal.Screen->UpdateObject(NET_SETUP_IP);	//Uloz ji a zobraz
			}
		}
		netSetupConnectState = NS_GET_GATEWAY;							//Prechod do dalsiho stavu
		DebugOut("Getting Gateway address...");
		WifiSendCommand(DRV_WIFI_GET_GATEWAY);							//Odeslani prikazu k ziskani brany
		break;
	case NS_GET_GATEWAY:
		NS_WAIT_FOR_FINISH();
		//Rozparsovani adresy brany
		while((wifiBuffer[i]!='\r') && (i <= 16))
		{
			myGateway[i] = wifiBuffer[i];
			i++;
		}
		myGateway[i] = 0;
		NetSetupInternal.Screen->UpdateObject(NET_SETUP_GATEWAY);
		
		netSetupConnectState = NS_GET_DNS;
		DebugOut("Getting DNS address...");
		WifiSendCommand(DRV_WIFI_GET_DNS);								//Odeslani prikazu k ziskani DNS
		break;
	case NS_GET_DNS:
		NS_WAIT_FOR_FINISH();											//Cekani na dokonceni
		{
			
			//Precteni IP adresy
			int i = 0;
			while(wifiBuffer[i]!='\r' && i <= 16)
			{
				myDNS[i] = wifiBuffer[i];
				i++;
			}
			myDNS[i] = 0;

			NetSetupInternal.Screen->UpdateObject(NET_SETUP_DNS);		//Update
		}
		
		netSetupConnectState = NS_COMPLETED;
		//Pokud nebyla ziskana platna IP adresa, zopakuj poslednich nekolik kroku 
		if (strcomp(myIP,(unsigned char*)"0.0.0.0"))
		{
			myConnectionState = CONNECTION_DISCONNECTED;
			netSetupConnectState = NS_IDLE;
            if (maxGetterCounter++ < 40)
            {
                WifiSendCommand(DRV_WIFI_GET_IP);
                netSetupConnectState = NS_GET_IP;
            }
		}
		else
             myConnectionState = CONNECTION_CONNECTED;							//JInak jsme pripojeni
		NetSetupInternal.Screen->UpdateObject(NET_SETUP_INFO);					//Aktualizace pribuznych objektu
        NetSetupInternal.Screen->UpdateObject(NET_SETUP_GATEWAY);
        NetSetupInternal.Screen->UpdateObject(NET_SETUP_IP);
        NetSetupInternal.Screen->UpdateObject(NET_SETUP_DNS);
        SendTaskMessage(STATUS_BAR, &DEFAULT_MSG_REFRESH);
		break;
	case NS_COMPLETED:
                
		break;

	}
	//POkud nedojde k odpovedi od wifi modulu dostatecne rychle, ma se za to, ze je odpojen nebo nefunkcni
    if ((GetElapsedTime(setupHandleStamp) > 5000 && (netSetupConnectState!= NS_ERROR &&  netSetupConnectState!= NS_AFTER_REBOOT  &&  netSetupConnectState!= NS_AFTER_REBOOT2 && netSetupConnectState!= NS_IDLE &&  netSetupConnectState!= NS_COMPLETED &&  netSetupConnectState!= NS_KEY)) || (GetElapsedTime(setupHandleStamp) > 50000 && netSetupConnectState == NS_KEY))
    {
        TDialogCfg cfg = {INFO,COUNTDOWN_NONE,100,(unsigned char*)STR_CONNECTOR_WIFI_FAILED,30};		//Sestaveni konfigurace dialogu
        MESSAGE dialogMessage = {CONFIG,&cfg};															//Sestaveni zpravy
        SendTaskMessage(DIALOG,&dialogMessage);															//Odeslani konfigurace
        NetSetupInternal.RunApplication(DIALOG);														//Spusteni dialogu
        WifiSendCommand((unsigned char*)"+++");															//Odeslani pokusu o opusteni SerialNet
		myConnectionState = CONNECTION_ERROR;															//Nastaveni chyboveho stavu
        LedOff(LED_4);
    }
}


/****************************************************************************
	Ridici stavovy automat aplikace

	Vstup: 
		neni

	Vystup
		neni

*****************************************************************************/
void AppNetSetup(void)
{
	switch (NetSetupInternal.State)
	{
	case NET_SETUP_NOT_INITIALIZED:
		break;
	case NET_SETUP_INITIALIZE:
		NetSetupInternal.State = NET_SETUP_READY;								//Prechod na dalsi stav
		if (netSetupInitialize() !=PASSED)										//Pokud se nezdarila inicializace
		{
			DebugOut("NetSetup could not be initialized. Falling to error.\n");
			NetSetupInternal.State = NET_SETUP_ERROR;							//Error
			break;
		}
		DebugOut("NetSetup initialized.\n");
		break;
	case NET_SETUP_RESTART:
		NetSetupInternal.Startup();												//Akce pro spusteni aplikace
		
		NetSetupInternal.State = NET_SETUP_DRAW;								//Prechod na dalsi stav
		break;
	case NET_SETUP_DRAW:
		NetSetupInternal.Screen->Draw();										//Vykresleni aplikace
		NetSetupInternal.State = NET_SETUP_ACTIVE;								//Orechod do daktivniho stavu
		break;
	case NET_SETUP_ACTIVE:
		NetSetupInternal.ProceedClick();										//Zpracovani kliknuti
		NSHandleConnection();													//rizeni spojeni
		break;
	case NET_SETUP_WAITING:
		switch(NetSetupInternal.TryToResume())									//Cekani na ukonceni aplikace
		{
		case KEYBOARD:
			switch(startingObject)												//Rozhodnuti o spoustejicim objektu
			{
			case NET_SETUP_IP:
				if (tryToGetIP(myIP,KeyboardBuffer.TextBuffer) == FAILED)		//Pokud se podari rozparsovat IP adresu
					break;
				if (tryToGetMask(myMask,KeyboardBuffer.TextBuffer) == FAILED)	//Pokud se podari rozparsovat masku
					break;
				strcopy(DRV_WIFI_SET_IP_start,commandBuffer);					//Odesli prikaz k nastaveni IP adresy
				str_append(commandBuffer,myIP);
				str_append(commandBuffer,DRV_LINEEND);
				WifiSendCommand(commandBuffer);
				netSetupConnectState = NS_AFTER_REBOOT2;						//Aktualizuj nastaveni
				break;
			case NET_SETUP_GATEWAY:
				if (tryToGetIP(myGateway,KeyboardBuffer.TextBuffer) == FAILED)	//To same pro branu i DNS
					break;

				strcopy(DRV_WIFI_SET_GATEWAY_start,commandBuffer);
				str_append(commandBuffer,myGateway);
				str_append(commandBuffer,DRV_LINEEND);
				WifiSendCommand(commandBuffer);
				netSetupConnectState = NS_AFTER_REBOOT2;
				break;
			case NET_SETUP_DNS:
				if (tryToGetIP(myDNS,KeyboardBuffer.TextBuffer) == FAILED)
					break;
				strcopy(DRV_WIFI_SET_DNS_start,commandBuffer);
				str_append(commandBuffer,myDNS);
				str_append(commandBuffer,DRV_LINEEND);
				WifiSendCommand(commandBuffer);

				netSetupConnectState = NS_AFTER_REBOOT2;
				break;
			case NET_SETUP_PASSWORD:
				if (KeyboardBuffer.TextBuffer[0] !=0)
				{
					strcopy(KeyboardBuffer.TextBuffer,myPassword);
				}
				netSetupConnectState = NS_CLEAR;
				break;
			}
			break;
		case NETWORK_NAMES:
			switch((NETWORK_NAMES_OBJECT) SendTaskMessage(NETWORK_NAMES,&DEFAULT_MSG_GET_RESULT))
			{
			case NETWORK_NAME_BUTTON_BACK:
				break;
			case NETWORK_NAME_BUTTON_OWN:
				strcopy(KeyboardBuffer.TextBuffer,mySSID);

				break;
			default:
				{
					//POkud jsme se vratili z NetworkNames
					//zaktualizuj InfoButton
					char pos = (char)SendTaskMessage(NETWORK_NAMES,&DEFAULT_MSG_GET_RESULT);
					strcopy(myDetectedNetworks[pos].ssid,mySSID);
					if (myDetectedNetworks[pos].strength > SIGNAL_BEST)
						mySignalStrength = SIGNAL_BEST;
					else if (myDetectedNetworks[pos].strength > SIGNAL_GOOD)
						mySignalStrength = SIGNAL_GOOD;
					else if (myDetectedNetworks[pos].strength > SIGNAL_WEAK)
						mySignalStrength = SIGNAL_WEAK;
					else
						mySignalStrength = SIGNAL_NONE;
					myCipher = myDetectedNetworks[pos].cipType;
					mySSIDType = myDetectedNetworks[pos].ssidType;
					strcopy((unsigned char*)int2char(myDetectedNetworks[pos].channel),myChannel);
				}
				break;
			}
			break;
		case NONE:
			break;
       case DIALOG:
            NetSetupInternal.State = NET_SETUP_STOP;
            break;
		default:
			DebugOut("Returned to NetSetup from unknown application.\n");
			break;
		}
		break;
	case NET_SETUP_READY:
		break;
	case NET_SETUP_STOP:
		NetSetupInternal.Stop();							//Korektni ukonceni aplikace
		netSetupConnectState = NS_MODULE_START;				//Nastaveni ridici smycky wifi do vychoziho stavu
		break;
	case NET_SETUP_ERROR:
		break;
	default:
		break;
	}
}