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

XCHAR Http_pRecvPacket[HTTP_MAX_RECV_LEN+1];

XCHAR Http_iRecvLen;
XCHAR Http_iState;
XSHORT Http_iCurMsgLen;
XLONG Http_lContentLen;
BOOLEAN Http_bBrokenLine;

#ifndef OEM_NET2PHONE
XLONG _lFileLength;
#endif

static XCHAR _pServerIP[IP_ALEN];
static XSHORT _iDstPort;

/////////////////////////////////////////////////////////////////////////////////////
//     Global Http function
////////////////////////////////////////////////////////////////////////////////////

#ifndef OEM_NET2PHONE
void _FillRequestLine()
{
	DCHAR iLen;

	p_line_start((PXCHAR)Adapter_pSendTcpData);
	p_line_add_c(Http_cMethodGet);
	p_line_add_c((PCCHAR)"/");
	iLen = SdramReadData(OPTIONS_SDRAM_POS+UPGRADE_FILENAME_LO);
	X_VAL(Sdram_pDataCache, iLen) = 0;
	p_line_add_x((PXCHAR)Sdram_pDataCache);
	p_line_add_space();
	p_line_add_c(Http_cName);
	p_line_add_newline();
}

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();

}

void _HttpGetFile()
{
	_FillRequestLine();
	_FillOtherHeader();
	Http_iCurMsgLen = p_line_get_len();
}

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

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 (iRespCode == 200)
	{
		CreateUpgradeFile();
	}
	else
	{
		CloseFileAndCheckLimit();
	}
	Http_iState = HTTP_STATE_REQUEST_BEGIN;
}


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);
		_lFileLength = Http_lContentLen;
	}
}

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;
			}
		}
	}
	Http_iRecvLen = 0;
}

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

	pCur = pData;
	iLen = iLength;

	while (iLen > 256)
	{
		SoloFileWrite(pCur, (UCHAR)256);
		iLen -= 256;
		pCur += 256;
	}
	if (iLen)
	{
		SoloFileWrite(pCur, (UCHAR)iLen);
	}
	DisplayFileStatus();
	Http_lContentLen -= iLen;
}

void HttpRunData()
{
	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 HttpUpgrade(UCHAR iType)
{
	Upgrade_iType = iType;
	_lFileLength = 0;
	ProvGetFileName();
	HttpClientStart(Upgrade_pServerIP, HTTP_SERVER_PORT);
}
#endif

void HttpClientInitialize()
{
	TcbInit(HTTP_SERVER_PORT, HTTP_TIME_OUT, HTTP_CLIENT_SDRAM_LO);
	Http_bBrokenLine = FALSE;
	Http_iState = HTTP_STATE_INIT;
	Http_iRecvLen = 0;
	Http_iCurMsgLen = 0;
	Http_lContentLen = 0;
}

void _ClientInitialize()
{
	// Tcp init
	Http_iState = HTTP_STATE_INIT;
	Http_iRecvLen = 0;
	Http_iCurMsgLen = 0;
	Http_lContentLen = 0;
	Http_bBrokenLine = FALSE;
}

void _ClinetHandleCloseEvent()
{
#ifdef OEM_NET2PHONE
	VoiceLineHandleCloseEvent();
#else
	if (_lFileLength)
	{
		SoloFileClose();
		if (Upgrade_iType == UPGRADE_GET_SET)
		{
			ProvHandleSetFile();
			if (Upgrade_iType != UPGRADE_GET_SET)
			{
				OutputVal(Upgrade_iType, IDS_CHECK_POINT_6);
				HttpClientStart(Upgrade_pServerIP, HTTP_SERVER_PORT);
				_lFileLength = 0;
			}
			else
			{
				CloseFileAndCheckLimit();
			}
		}
		else
		{
			ProvStartUpgrade();
		}
	}
	else
	{
		OnProvisionEnd();
	}
#endif
}

BOOLEAN HttpClientRun()
{
	if (!TcbRun(HTTP_CLIENT_SDRAM_LO))	return FALSE;

	if (Tcp_bAcceptEvent)
	{
		Tcp_bAcceptEvent = FALSE;
	}

	if (Tcp_bConnectEvent)
	{
		Tcp_bConnectEvent = FALSE;
#ifdef OEM_NET2PHONE
		VoiceLineHandleConnectEvent();
#else
		_HttpGetFile();
#endif
	}

    if (Tcp_bDataEvent)
    {
#ifdef OEM_NET2PHONE
		VoiceLineHandleDataEvent();
#else
		HttpRunData();
#endif
		Tcp_bDataEvent = FALSE;
    }

    if (Tcp_bCloseEvent)
	{
		TcpClose(HTTP_CLIENT_SDRAM_LO);
	}

	TcpSend(Http_iCurMsgLen);
	Http_iCurMsgLen = 0;

	if (TcbAcked())
	{
#ifdef OEM_NET2PHONE
		VoiceLineHandleExtraTask();		//	Handle extra task
#else
#endif
	}
    if (Tcp_bCloseEvent)
    {
		Tcp_bCloseEvent = FALSE;
		_ClientInitialize();
		_ClinetHandleCloseEvent();
	}

	if (Tcp_bResetEvent)
	{
		Tcp_bResetEvent = FALSE;
#ifdef OEM_NET2PHONE
		VoiceLineHandleResetEvent();
#else
		CloseFileAndCheckLimit();
#endif
	}
	return TRUE;
}

void HttpClientHandleTimer()
{
	if (TcbHandleTimer(HTTP_CLIENT_SDRAM_LO))
	{
		return;
	}

	OutputString(IDS_HTTP_TIMER_FAIL);

	// Handle time out failure
	TcpSendClose(HTTP_CLIENT_SDRAM_LO);
#ifdef OEM_NET2PHONE
	VoiceLineHandleTimerOut();
#else
	CloseFileAndCheckLimit();
#endif
}

void HttpClientStart(PXCHAR pDstIP, USHORT iDstPort)
{
	_ClientInitialize();
	p_memcpy_ip(_pServerIP, pDstIP);
	_iDstPort = iDstPort;
	HttpClientStartAgain();
}

void HttpClientStartAgain()
{
	TcbInit((USHORT)(TCP_SRC_PORT_MIN + p_rand_char()), HTTP_TIME_OUT, HTTP_CLIENT_SDRAM_LO);
	TcpOpen(_pServerIP, _iDstPort, HTTP_CLIENT_SDRAM_LO);
}
