#include "p_apps.h"
#include "v_task.h"
#include "p_http.h"
#include "autoprov.h"

#ifdef OEM_NET2PHONE

#define CLIENT_STATE_INIT	0
#define CLIENT_STATE_GET1	1
#define CLIENT_STATE_GET2	2
#define CLIENT_STATE_GET3	3

static CCHAR _cDeviceName[] = "koncept";
static CCHAR _cUserName[] = "voipphone";
static CCHAR _cPassword[] = "ke1021a";

static XCHAR _iClientState;
static BOOLEAN _bStartConn;

/******************************************************************************
***** Fucntions to compose messages to be sent ********************************
*******************************************************************************/
void _Mac2String(PXCHAR pMac, PXCHAR pString)
{
	DCHAR i, iVal, iPos;

	iPos = 0;
	for (i = 0; i < HW_ALEN; i ++)
	{
		iVal = pMac[i];
		if (iVal < 0x10)
		{
			pString[iPos] = '0';
			iPos ++;
			p_itoa(iVal, (PXCHAR)(pString+iPos), 16);
			iPos ++;
		}
		else
		{
			p_itoa(iVal, (PXCHAR)(pString+iPos), 16);
			iPos += 2;
		}
	}
	pString[iPos] = 0;
}

void _InitRequestUri()
{
	p_line_start((PXCHAR)Sdram_pDataCache);
	p_line_add_char('/');
	p_line_add_c(_cDeviceName);
	p_line_add_char('/');
	p_line_add_c((PCCHAR)"prov.aspx?id=");
	_Mac2String(Local_pMacAddress, p_line_get_buf());
	p_line_update_len();
	p_line_add_c((PCCHAR)"&ver=");
	p_line_add_c(g_cSoftwareVersion);
	HttpWriteData(HTTP_CLIENT_REQUEST_URI, (UCHAR)p_line_get_len());
}

void _FillRequestLine()
{
	p_line_start((PXCHAR)Adapter_pSendTcpData);
	p_line_add_c(Http_cMethodGet);
	HttpAddString(HTTP_CLIENT_REQUEST_URI);
	p_line_add_space();
	p_line_add_c(Http_cName);
	p_line_add_newline();
}

void _FillAuth()
{
	HttpFillAuth(HTTP_WWW_AUTH_RESP);
	HttpFillAuth(HTTP_PROXY_AUTH_RESP);
}

void _FillOtherHeader()
{
	p_line_add_c((PCCHAR)"Pragma: no-cache");
	p_line_add_newline();
	p_line_add_c((PCCHAR)"Accept: */*");
	p_line_add_newline();
	p_line_add_c((PCCHAR)"Host: ");
	p_line_add_x(Sys_pUpgradeAddr);
	p_line_add_newline();
	p_line_add_c(Http_cConnection);
	p_line_add_c((PCCHAR)"close");
	p_line_add_newline();
	p_line_add_newline();
}

USHORT _ClientFillData()
{
	switch (_iClientState)
	{
	case CLIENT_STATE_GET1:
		_FillRequestLine();
		_FillOtherHeader();
		return p_line_get_len();

	case CLIENT_STATE_GET2:
		_FillRequestLine();
		_FillAuth();
		_FillOtherHeader();
		return p_line_get_len();

	case CLIENT_STATE_GET3:
		_FillRequestLine();
		_FillOtherHeader();
		return p_line_get_len();
	}

	return 0;
}


/******************************************************************************
***** Fucntions to handle received messages ***********************************
*******************************************************************************/

void _ClientDone()
{
	_iClientState = CLIENT_STATE_INIT;
	CloseFileAndCheckLimit();
}

void _ClientHandleFirstLine()
{
	DSHORT iRespCode;
	PXCHAR_D pCur;
	PXCHAR_D pTemp;
	
	pCur = Http_pRecvPacket;
	
	pTemp = p_strchr_x(pCur, ' ');
	if (!pTemp)	
	{
		Http_iState = HTTP_STATE_INIT;
		return;
	}
	pTemp[0] = 0;

	if (p_strcmp_c2x(pCur, Http_cName))
	{
		Http_iState = HTTP_STATE_INIT;
		return;
	}
	pCur = pTemp;
	pCur ++;
	iRespCode = p_atoi(pCur, 10);
	if (_iClientState == CLIENT_STATE_GET1)
	{
		if (iRespCode == 200)
		{
			_iClientState = CLIENT_STATE_GET2;
		}
		else if (iRespCode != 401)
		{
			_iClientState = CLIENT_STATE_INIT;
		}
	}
	else if (_iClientState == CLIENT_STATE_GET2)
	{
		if (iRespCode != 200)
		{
			DisplayString((PCCHAR)"password error", 1);
			_iClientState = CLIENT_STATE_INIT;
		}
	}
	else if (_iClientState == CLIENT_STATE_GET3)
	{
		if (iRespCode == 200)
		{
			CreateUpgradeFile();
		}
		else
		{
			_iClientState = CLIENT_STATE_INIT;
		}
	}

	Http_iState = HTTP_STATE_REQUEST_BEGIN;
}


void _GenAuth(UCHAR iType, PXCHAR pData)
{
	DCHAR iLen;

	HttpAuthInit();

	iLen = HttpReadData(HTTP_CLIENT_REQUEST_URI);
	if (iLen)	HttpWriteData(HTTP_AUTH_URI, iLen);

	p_strcpy_c2x((PXCHAR)Sdram_pDataCache2, _cUserName);
	HttpSaveString(HTTP_AUTH_ACCOUNT, (PXCHAR)Sdram_pDataCache2);
	p_strcpy_c2x((PXCHAR)Sdram_pDataCache2, _cPassword);
	HttpSaveString(HTTP_AUTH_PASSWORD, (PXCHAR)Sdram_pDataCache2);

	HttpGenAuth(pData, (PCCHAR)"GET", iType);
}

void _ClientHandleHeader()
{
	PXCHAR_D pCur;

	pCur = Http_pRecvPacket;
	if (p_memcmp_nocase_c2x(pCur, Http_cContentLength, CONTENT_LENGTH_LABEL_LEN))
	{
		Http_lContentLen = p_atol((PXCHAR)(pCur + CONTENT_LENGTH_LABEL_LEN), 10);
		OutputVal((USHORT)Http_lContentLen, IDS_CHECK_POINT_0);
	}
	else if (p_memcmp_nocase_c2x(pCur, Http_cWWWAuthenticate, WWW_AUTHENTICATE_LABEL_LEN))
	{
		pCur += WWW_AUTHENTICATE_LABEL_LEN;
		_GenAuth(HTTP_AUTH_TYPE_WWW, pCur);
	}
	else if (p_memcmp_nocase_c2x(pCur, Http_cProxyAuthenticate, PROXY_AUTHENTICATE_LABEL_LEN))
	{
		pCur += PROXY_AUTHENTICATE_LABEL_LEN;
		_GenAuth(HTTP_AUTH_TYPE_PROXY, pCur);
	}
}

void _ClientHandleContent(PXCHAR pData, USHORT iLength)
{
	PXCHAR_D pCur;

	pCur = pData;
	if (_iClientState == CLIENT_STATE_GET2)
	{
		OutputPXCHAR(pData, iLength);
		pCur[iLength] = 0;
		pCur += 7; // http://
		pCur = p_strchr_x(pCur, '/');
		HttpSaveString(HTTP_CLIENT_REQUEST_URI, pCur);
	}
	else if (_iClientState == CLIENT_STATE_GET3)
	{
		while (iLength > 256)
		{
			SoloFileWrite(pCur, (UCHAR)256);
			iLength -= 256;
			pCur += 256;
		}
		if (iLength)
		{
			SoloFileWrite(pCur, (UCHAR)iLength);
		}
		DisplayFileStatus();
	}
	Http_lContentLen -= iLength;
}

void _ClientSaveHeader(UCHAR iVal)
{
	if (Http_iRecvLen < HTTP_MAX_RECV_LEN)
	{
		Http_pRecvPacket[Http_iRecvLen] = iVal;
		Http_iRecvLen ++;
	}
}

void _ClientParseLine()
{
	Http_pRecvPacket[Http_iRecvLen] = 0;
	if (Http_iState == HTTP_STATE_INIT)
	{
		_ClientHandleFirstLine();
	}
	else if (Http_iState == HTTP_STATE_REQUEST_BEGIN)
	{
		if (Http_iRecvLen)
		{
			_ClientHandleHeader();
		}
		else 
		{
			if (Http_lContentLen)
			{
				Http_iState = HTTP_STATE_REQUEST_HEAD_END;
			}
			else
			{
				Http_iState = HTTP_STATE_INIT;
				if (_iClientState == CLIENT_STATE_GET2 || _iClientState == CLIENT_STATE_GET3)
				{
					DebugCString((PCCHAR)"No need to upgrade!");
					_iClientState = CLIENT_STATE_INIT;
				}
			}
		}
	}
	Http_iRecvLen = 0;
}

// global functions

void VoiceLineHandleConnectEvent()
{
	Http_iCurMsgLen = _ClientFillData();
}

void VoiceLineHandleDataEvent()
{
	DCHAR iVal, iNextVal;
	DSHORT iIndex;

	iIndex = 0;
	while (iIndex < Adapter_iReceiveLen)
	{
		if (Http_iState < HTTP_STATE_REQUEST_HEAD_END)
		{
			iVal = X_VAL(Adapter_pReceiveTcpData, iIndex);
			iIndex ++;
			if (iVal == 0x0d)
			{
				if (iIndex < Adapter_iReceiveLen)
				{
					iNextVal = X_VAL(Adapter_pReceiveTcpData, iIndex);
					iIndex ++;
					if (iNextVal == 0x0a)
					{
						_ClientParseLine();
					}
					else
					{
						_ClientSaveHeader(iVal);
						_ClientSaveHeader(iNextVal);
					}
				}
				else
				{
					Http_bBrokenLine = TRUE;
				}
			}
			else if (iVal == 0x0a)
			{
				if (Http_bBrokenLine)
				{
					_ClientParseLine();
					Http_bBrokenLine = FALSE;
				}
				else
				{
					_ClientSaveHeader(iVal);
				}
			}
			else
			{
				_ClientSaveHeader(iVal);
			}
		}
		else 
		{
			if (Http_lContentLen)
			{
				_ClientHandleContent((PXCHAR)(Adapter_pReceiveTcpData+iIndex), (USHORT)(Adapter_iReceiveLen - iIndex));
			}
			break;
		}
	}
}

void VoiceLineStartUpgrade(PXCHAR pDstIP, USHORT iDstPort)
{
	_InitRequestUri();
	_iClientState = CLIENT_STATE_GET1;
	_bStartConn = FALSE;
	HttpClearAuth();
	HttpClientStart(pDstIP, iDstPort);
	Upgrade_iType = UPGRADE_GET_BIN;
}

void VoiceLineHandleExtraTask()
{
	if (_iClientState == CLIENT_STATE_INIT)
	{
		_ClientDone();
	}
	else
	{
		if (_bStartConn)
		{
			HttpClientStartAgain();
			_bStartConn = FALSE;
		}
	}
}

void VoiceLineHandleCloseEvent()
{
	_bStartConn = FALSE;
	if (_iClientState == CLIENT_STATE_GET1)
	{
		_iClientState = CLIENT_STATE_GET2;
		_bStartConn = TRUE;
	}
	else if (_iClientState == CLIENT_STATE_GET2)
	{
		_iClientState = CLIENT_STATE_GET3;
		_bStartConn = TRUE;
	}
	else if (_iClientState == CLIENT_STATE_GET3)
	{
		SoloFileClose();
		ProvStartUpgrade();
	}
}

void VoiceLineHandleResetEvent()
{
	_ClientDone();	
}

void VoiceLineHandleTimerOut()
{
	_ClientDone();	
}

#endif
