#include "p_apps.h"
#include "v_task.h"

#define TIME_OFFSET_SECONDS		43200	// 48 * 900 = 43200

static CCHAR _cTimeZoneTable[TIME_ZONE_MAX] = {
0,  4,  8,  12, 16, 20, 20, 20, 24, 24, 24, 24, 28, 28, 28, 32, 32, 32, 34, 36, 36, 36, 40, 44, 
44, 48, 48, 52, 52, 52, 52, 52, 56, 56, 56, 56, 56, 56, 60, 60, 60, 60, 62, 64, 64, 66, 68, 68,
70, 71, 72, 72, 72, 74, 76, 76, 80, 80, 80, 80, 80, 84, 84, 84, 86, 86, 88, 88, 88, 88, 88, 92,
96, 96, 100};
 
BOOLEAN Sntp_bFinished; 

static BOOLEAN _bFinding;
static XCHAR _iTimer, _iRetries, _iDnsIndex;

ULONG TimeCompute()
{
	DCHAR iDayLightOffset;
	DLONG lTime;

	iDayLightOffset = (Sys_iTimeZone & TIMEZONE_DAYLIGHT_OR) ? 4 : 0;
	iDayLightOffset += _cTimeZoneTable[Sys_iTimeZone&TIMEZONE_DAYLIGHT_AND];
	lTime = iDayLightOffset;
	lTime *= 900;
	lTime -= TIME_OFFSET_SECONDS;
	return lTime;
}

void SntpRun()
{	
	_iTimer = 0;
	_iDnsIndex = 1;
	Sys_lCurrentTime = PXCHAR2ULONG((PXCHAR)(Adapter_pReceiveUdpData+40));
	Sys_lCurrentTime += TimeCompute();
	p_srand((USHORT)(Sys_lCurrentTime+p_randseed_from_mac()));
	_bFinding = FALSE;
	Sntp_bFinished = TRUE;

	TaskLogon();
}

void SntpInitialize()
{
	Sntp_bFinished = FALSE; 
	_bFinding = FALSE;
	_iRetries = 0;
	_iTimer = 0;
}

void _SendSntp()
{
	PXCHAR_D pCur;

	pCur = (PXCHAR)Adapter_pSendUdpData;
	p_memset_x(pCur, 0, 48);	//Preparing 48 byte NTP packet

	//Set Flags: (00) leap indicator no warning, (011) NTP version 3, (011) SNTP Client
	pCur[0] = 0x1b;

	//transmit UNIX time to Julian time. (in seconds)
	pCur += 40;
	ULONG2PUCHAR(Sys_lCurrentTime - TimeCompute(), pCur);

	UdpSend(48, SNTP_SDRAM_LO);
}

void SntpSend(PXCHAR pServerIP)
{
	if (IsValidIP(pServerIP))
	{
		UdpOpen(pServerIP, SNTP_SERVER_PORT, SNTP_SRC_PORT, SNTP_SDRAM_LO);
		_SendSntp();
		_bFinding = TRUE;
	}
	else
	{
		SntpRetry();
	}
}

void SntpRetry()
{
	_iDnsIndex ++;
	if (_iDnsIndex < SNTP_DNS_NUM)
	{
		Task_iDnsType = DNS_TYPE_SNTP;
		SdramRead(STRING_SDRAM_HI, (UCHAR)(SNTP_DNS_SDRAM_LO+_iDnsIndex), SRAM_DMA_HALF_DWORD);
		DnsSend((PXCHAR)Sdram_pDataCache, FALSE);
	}
	else
	{
		Task_iDnsType = DNS_TYPE_NONE;
		TaskLogon();
	}
}

void SntpHandleTimer()
{
	if (!_bFinding)		return;

	_iTimer ++;
	if (_iTimer >= TCPIP_RESET_TIME)
	{
		_iRetries ++;
		_iTimer = 0;
		if (_iRetries >= TCPIP_MAX_RETRY)
		{
			SntpInitialize();
			SntpRetry();
		}
		else
		{
			_SendSntp();
		}
	}
}

void SntpDisplayHandleTimer()
{
	XCHAR pBuf[DISPLAY_MAX_CHAR+1];

	if (Sntp_bFinished)
	{
		if (!(Sys_lCurrentTime % 60))
		{
			GetDateTimeDisplay(pBuf, TRUE, Sys_lCurrentTime);
			DisplayLine(pBuf, 0);
		}
		_iTimer ++;
		if (!_iTimer)
		{
			_iDnsIndex ++;
			if (!_iDnsIndex)
			{
				SntpStart();
			}
		}
	}
	else
	{
		if (!(Sys_lCurrentTime % 600))	// try to get time every 10 minutes
		{
			SntpStart();
		}
	}
}

void SntpStart()
{
	if (IsBroadcastIP(Sys_pNtsIP))
	{
		TaskLogon();
	}
	else
	{
		SntpInitialize();
		_iDnsIndex = 255;
		SntpSend(Sys_pNtsIP);
	}
}


