/*-------------------------------------------------------------------------
   AR1688 SNTP function copy right information

   Copyright (c) 2006-2015. Tang, Li <tangli@palmmicro.com>
                            Lin, Rongrong <woody@palmmicro.com>

   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of Palmmicro nor the names of its contributors may be
	  used to endorse or promote products derived from this software without
	  specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   DISCLAIMED. IN NO EVENT SHALL COPYRIGHT OWNER BE LIABLE FOR ANY
   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------*/

#include "version.h"
#include "type.h"
#include "ar168.h"
#include "core.h"
#include "apps.h"
#include "tcpip.h"
#include "sfr.h"

/*
"time.windows.com",
"time.nist.gov",
"swisstime.ethz.ch",
"pool.ntp.org",
*/

#ifdef OEM_IM
#define APP_SERVER_PORT	40005
#define APP_SRC_PORT		40005
#define P_MAX_LEN    64   //协议最大字节数为64字节，此值最大不能超过100字节

#define WIN_OPEN   '0'
#define WIN_END    '1'
#define WIN_PAUSE_TALK  '2'//暂停通话
#define WIN_PAUSE_TIME  '3'//暂停计时
#define WIN_LIGHT_OUT '4'
#define WIN_LIGHT_ON '6'  //点亮屏幕
#define WIN_READY     '5' //窗口已加载
#define POWER_ON      '7' //显示窗口名称和是哪一侧的话机
#define HELP_ANSWER 'r'
#define REBOOT 'R'



UDP_SOCKET _pAppSocket;
UCHAR AppServerIP[IP_ALEN];
extern volatile UCHAR _bLightStatus;
extern volatile BOOLEAN _bHelpStatus;
BOOLEAN _bdelaysend;







void UdpSockSend(PCHAR pBuf, USHORT len, PCHAR DestIP, USHORT DestPort)
{
	PCHAR pCur;
	if (_pAppSocket != 0)
	{
		pCur = Adapter_pUdpBuf;
		memset(pCur, 0, len+1);	//Preparing len+5 byte packet
		memcpy(pCur, pBuf, len);
		UdpSendTo(_pAppSocket, len+1, DestIP, DestPort);
	}
}

void UdpSockClose()
{
	UdpClose(_pAppSocket);
	return;
}


const UCHAR _hint[] = "剩余     分钟";
const UCHAR _wopen[] = "   会见开始   ";
const UCHAR _wend[] = "   会见结束   ";
const UCHAR _wpause_talk[] = "   暂停通话   ";
const UCHAR _wpause_time[] = "   暂停计时   ";
const UCHAR _wready[] = "   准备开始   ";
const UCHAR _wblank[] = "              ";
const UCHAR _hint_prisoner[] = "  会见人话机  ";
const UCHAR _hint_relation[] = "   家属话机   ";

void _CmdDeal(PCHAR rBuf,USHORT rLen)
{
	UCHAR pBuf[DISPLAY_MAX_CHAR];
	UCHAR recv_buf[P_MAX_LEN];
	PCHAR pCur;
	
	memset(recv_buf,0,P_MAX_LEN);
	if(rLen > P_MAX_LEN-1) //超过能处理的最大缓冲区
	{
		memcpy(recv_buf,rBuf,P_MAX_LEN-1);
		UdpDebugString("The length of data received is too long to deal,give up!");//UdpDebugString最大字节数是100
		UdpDebugString(recv_buf);
		return;
	}
	UdpDebugVal(rLen,10);
	UdpDebugString(recv_buf);
	memcpy(recv_buf,rBuf,rLen);
	if (recv_buf[0] == (UCHAR)'C' && recv_buf[1] == (UCHAR)'M' && recv_buf[2] == (UCHAR)'D' && recv_buf[3] == (UCHAR)'=')
	{
  	switch(recv_buf[4])
  	{
  		case WIN_OPEN:
  			if(rLen == 25)//CMD=0x    张三     \r\n\r\n,尾部有一个0作为字符串结束共25个字节
  			{
  				recv_buf[20] = 0;
  				strcpy(pBuf, recv_buf+6);
  			}
  			else
  			{
  				strcpy(pBuf, _wopen);
  			}
  			LcdDisplayIM(pBuf,0);
  			strcpy(pBuf, _hint);
  			pCur = pBuf+5;
  			if(recv_buf[5] > 99)//para不能大于255，也就是说最大4个小时
  			{
  				pCur[0] = div_16x8(recv_buf[5], 100) + '0';
  				pCur[1] = div_16x8(mod_16x8(recv_buf[5], 100),10) + '0';
  				pCur[2] = mod_16x8(recv_buf[5], 10) + '0';
  			}
  			else if(recv_buf[5] > 9)
  			{
  				pCur[0] = ' ';
  				pCur[1] = div_16x8(recv_buf[5], 10) + '0';
  				pCur[2] = mod_16x8(recv_buf[5], 10) + '0';
  			}
  			else
  			{
  				pCur[0] = ' ';
  				pCur[1] = ' ';
  				pCur[2] = recv_buf[5] + '0';
  			}
  			LcdDisplayIM(pBuf,1);
  			rGPIO_A &= 0xfd;//A1 on 点亮lcd背光灯
  			break;
  			
  		case WIN_END:
  			strcpy(pBuf, _wend);
  			LcdDisplayIM(pBuf,0);
  			strcpy(pBuf, _hint);
  			pBuf[5] = ' ';
  			pBuf[6] = ' ';
  			pBuf[7] = '0';
  			LcdDisplayIM(pBuf,1);
  			break;
  			
  		case WIN_PAUSE_TALK://暂停通话
  			strcpy(pBuf, _wpause_talk);
  			LcdDisplayIM(pBuf,0);
  			strcpy(pBuf, _hint);
  			pCur = pBuf+5;
  			if(recv_buf[5] > 99)//para不能大于255，也就是说最大4个小时
  			{
  				pCur[0] = div_16x8(recv_buf[5], 100) + '0';
  				pCur[1] = div_16x8(mod_16x8(recv_buf[5], 100),10) + '0';
  				pCur[2] = mod_16x8(recv_buf[5], 10) + '0';
  			}
  			else if(recv_buf[5] > 9)
  			{
  				pCur[0] = ' ';
  				pCur[1] = div_16x8(recv_buf[5], 10) + '0';
  				pCur[2] = mod_16x8(recv_buf[5], 10) + '0';
  			}
  			else
  			{
  				pCur[0] = ' ';
  				pCur[1] = ' ';
  				pCur[2] = recv_buf[5] + '0';
  			}
  			LcdDisplayIM(pBuf,1);
  			rGPIO_A &= 0xfd;//A1 on 点亮lcd背光灯
  			break;
  			
  		case WIN_PAUSE_TIME://暂停计时
  			strcpy(pBuf, _wpause_time);
  			LcdDisplayIM(pBuf,0);
  			break;
  			
  		case WIN_READY:
  			strcpy(pBuf, _wready);
  			LcdDisplayIM(pBuf,0);
  			if(rLen == 24)//CMD=5    张三     \r\n\r\n,尾部有一个0作为字符串结束，共24个字节
  			{
  				recv_buf[19] = 0;
  				strcpy(pBuf, recv_buf+6);
  			}
  			else
  			{
  				strcpy(pBuf, _wblank);
  			}
  			LcdDisplayIM(pBuf,1);
  			break;
  			
  		case WIN_LIGHT_OUT:
  			rGPIO_A |= 0x02;//A1 off 灭掉lcd背光灯
  			LcdStart();//清屏幕
  			break;
  			
  		case WIN_LIGHT_ON:
  			rGPIO_A &= 0xfd;//A1 on 点亮lcd背光灯
  			break;

  		case HELP_ANSWER:
  			if(recv_buf[5] == '1')//求助灯闪
  			{
  				_bLightStatus = 2;
  			}
  			else//灭求助灯
  			{
  				_bLightStatus = 0;
  			}
  			break;
  			
  		case POWER_ON:
  			if(rLen == 25)//CMD=7x    窗口1     \r\n\r\n,尾部有一个0作为字符串结束共25个字节
  			{
  				recv_buf[20] = 0;
  				strcpy(pBuf, recv_buf+6);
  			}
  			else
  			{
  				strcpy(pBuf, _wopen);
  			}
  			LcdDisplayIM(pBuf,0);
  			if(recv_buf[5] == '1')//罪犯侧话机
  			{
  				strcpy(pBuf, _hint_prisoner);
  			}
  			else//家属侧话机
  			{
  				strcpy(pBuf, _hint_relation);
  			}
  			LcdDisplayIM(pBuf,1);
  			rGPIO_A &= 0xfd;//A1 on 点亮lcd背光灯
  			break;
  			
  		case REBOOT:
  			UdpDebugString("rebooting...");
  			FlashReboot();
  			break;
  	}
  }
  UdpDebugString(recv_buf);
}

void UdpSockRun(UDP_SOCKET pUcb)
{
	PCHAR pBuf;

	if (pUcb != _pAppSocket)	
		return;
	pBuf = Adapter_pUdpBuf;
	_CmdDeal(pBuf,pUcb->sLen);
}

void LightTimer()
{
	PCHAR usernumber;
	UCHAR sBuf[64];
	
	switch(_bLightStatus)
	{
		case 0:
			rGPIO_A |= 0x04;//A2 off
  		_bHelpStatus = FALSE;//灯灭退出求助状态，可以再按求助
			break;
			
		case 1:
			rGPIO_A &= 0xfb;//A2 on 亮1秒钟，并发送消息，如果没有回应就灭掉，如果有回应就闪
			memset(sBuf,0,64);
			strcpy(sBuf,"cmd=help\r\n"
		      	      "client=");
			usernumber = sBuf + strlen(sBuf);
			OptionsGetString(usernumber, OPT_USER_NUMBER, 16);
			strcat(sBuf,"\r\n\r\n");
			UdpSockSend(sBuf,strlen(sBuf),AppServerIP,APP_SERVER_PORT);

			_bLightStatus = 0;
			break;
			
		case 2:
  		if (rGPIO_A & 0x04)		// GPIO_A2 Off?
  		{
  			rGPIO_A &= 0xfb;//A2 on
  		}
  		else
  		{
  			rGPIO_A |= 0x04;//A2 off
  		}
			break;
	}
	if(_bdelaysend)
	{
			if(Sys_pIpAddress[0] == 0)
			{
				UdpDebugString("ip address is 0.0.0.0,waiting for getting ip");
			}
			else
			{
				memset(sBuf,0,64);
				strcpy(sBuf,"cmd=get_status\r\n"
				            "client=");
				usernumber = sBuf + strlen(sBuf);
				OptionsGetString(usernumber, OPT_USER_NUMBER, 16);
				strcat(sBuf,"\r\n\r\n");
				UdpSockSend(sBuf,strlen(sBuf),AppServerIP,APP_SERVER_PORT);
				_bdelaysend = FALSE;
			}
	}
}

void UdpSockOpen(PCHAR pServerIP)
{
	UCHAR usernumber[16];
	UCHAR sBuf[64];
	
	if (pServerIP)
	{
		if (!_pAppSocket)
		{
			_pAppSocket = UdpListen(APP_SRC_PORT, NET_BANK_OFFSET, (USHORT)UdpSockRun);
			//使用UdpConnectTo会将本socket只用于connect to的server及端口，其他ip或端口发来的数据不会被处理，
			//UdpConnectTo和UdpSend是成对使用的，也就是说UdpSend只能用于之前调用过UdpConnectTo的socket
			//如果想接收非connect to的ip及端口的数据则不能使用UdpConnectTo，只UdpListen就行了，同时发送时要使用UdpSendTo
//			UdpConnectTo(_pAppSocket, pServerIP, APP_SERVER_PORT);
			memset(sBuf,0,64);
			strcpy(sBuf,"cmd=get_status\r\n"
			            "client=");
			OptionsGetString(usernumber, OPT_USER_NUMBER, 16);
			strcat(sBuf,usernumber);
			strcat(sBuf,"\r\n\r\n");
			if(Sys_pIpAddress[0] == 0)
			{
				UdpDebugString("ip address is 0.0.0.0,waiting for getting ip");
				_bdelaysend = TRUE;
			}
			else
				UdpSockSend(sBuf,strlen(sBuf),pServerIP,APP_SERVER_PORT);
			UdpDebugString(sBuf);
		}
	}
	else
	{
		UdpSockClose();
		UdpDebugString("Server ip is NULL");
	}
}


void UdpSockInit()
{
	UCHAR pServer_str[24];
	UCHAR pServer_tmp[IP_ALEN+2];

//初始化udp socket	
	_pAppSocket = NULL;
	_bLightStatus = 0;
	_bdelaysend = FALSE;
	memset(pServer_str,0,24);
	memset(pServer_tmp,0,IP_ALEN+2);
	OptionsGetString(pServer_str, OPT_SIP_PROXY, 24);//使用sip server作为应用服务器
	str2ip(pServer_str, pServer_tmp);
	memcpy4(AppServerIP,pServer_tmp);
	UdpSockOpen(AppServerIP);
	UdpDebugString("udp server now listen on port 40005");


}



#else
#endif

