#include "lwip/opt.h"
#include "lwip/sys.h"
#include "tcp_server.h"
#include <string.h>
#include <stdio.h>
#include "stm32f2xx.h"
#include "main.h"
#include "lwip/tcp.h"
#include "lwip/memp.h"
#include "lwip/api.h"
#include "lwip/sockets.h"
#include "log.h"
#include "app_ethernet.h"
#include "gateway_message.h"
#include "stdlib.h"
#include "timer.h"
#include "sys_mqtt.h"
#include "updata.h"
#include "app_ethernet.h"
#include "stm32f2xx_hal.h"
#include "myFile.h"
#include "app_ethernet.h"

uint8_t closeFlag = 0;				// DHCP关闭标志位
uint8_t ProtocolsModeFlag = 1;// 默认 ：开启内置协议模式
uint8_t TransparentModeFlag = 0;	// 表示用串口透传 将数据原封不动的发给客户端

ip_config load_ip_config = {0};
ip_config *get_ip_config()
{
    return &load_ip_config;
}

#if 1
// 解析设备当前的硬件信息（结构体内的数据）
void get_device_params(char* device_params)
{
	GATEWAY_PARAMS *get;
	get= get_gateway_config_params();
	DEVICE_PARAMS *current_device=get->device_params;
	sprintf(device_params, "{\"read_config\":\"success\",\"baudrate\":%d,\"checkBit\":%d,\"commandTopic\":\"%s\",\"dataBit\":%d,\
\"deviceId\":\"%s\",\"host\":\"%s\",\"inboundTime\":%d,\"messageTopic\":\"%s\",\"port\":%d,\"stopBit\":%d,\"deviceList\":[",get->baudrate,
			get->checkBit,get->commandTopic,get->dataBits,get->deviceId,get->host,get->inboundTime,get->messageTopic,get->port,get->stopBit);
	while(current_device != NULL)
	{	
		sprintf(device_params + strlen(device_params),"{\"protocol\":%d,\"bigLittleFormat\":%d,\"deviceId\":\"%s\",\"sensorData\":[",
												current_device->protocol,current_device->MDBbigLittleFormat,current_device->deviceID);
			GATEWAY_READ_DLT645_COMMAND *read_dlt645_command = current_device->params->gateway_read_dlt645_command;
			GATEWAY_READ_MODBUS_COMMAND *read_modbus_command = current_device->params->gateway_read_modbus_command;
			GATEWAY_WRITE_MODBUS_COMMAND *write_modbus_command = current_device->params->gateway_write_modbus_command;
			
			// dlt645 read
			while(read_dlt645_command != NULL)
			{	
				sprintf(device_params + strlen(device_params),"{\"identifier645\":%d,\"identifier\":\"%s\",\"deviceID645\":\"%s\"},",
											read_dlt645_command->Identification,read_dlt645_command->keyword,read_dlt645_command->deviceID645);
				read_dlt645_command = read_dlt645_command->nextParams;
			}
		
			// modbus read
			while(read_modbus_command != NULL)
			{
				sprintf(device_params + strlen(device_params),"{\"rFunctionCode\":%d,\"registerAddress\":%d,\"slaveAddress\":%d,\"registerByteNum\":%d,\"identifier\":\"%s\",\"precise\":%d},",
																											read_modbus_command->functionCode, read_modbus_command->registerAddress,read_modbus_command->slaveAddress,
																											read_modbus_command->registerByteNum,read_modbus_command->keyword,read_modbus_command->decimalPoint);
				read_modbus_command = read_modbus_command->nextParams;
			}
			
			// modbus write
			sprintf(device_params + strlen(device_params)-1,"], \"commandData\":[");//sensorData:[ 
			while(write_modbus_command != NULL)
			{
				sprintf(device_params + strlen(device_params),"{\"registerAddress\":%d,\"slaveAddress\":%d,\"wFunctionCode\":%d,\"registerByteNum\":%d},",
								write_modbus_command->registerAddress,write_modbus_command->slaveAddress,write_modbus_command->functionCode,write_modbus_command->registerByteNum);
				write_modbus_command = write_modbus_command->nextParams;
			}		
			sprintf(device_params + strlen(device_params)-1,"]},");// commandData:[
			current_device = current_device->nextDevice;	
	}
	sprintf(device_params + strlen(device_params) -1 ,"]}");
}

// 储存上位机发送的config数据，并返回上位机操作结果
void save_config(int client_socket,char* buf)
{
		GATEWAY_PARAMS *get;
		get= get_gateway_config_params();
		char* saveData = mymalloc(SRAMEX,20 * 1024);//(RECV_BUF_SIZE);// 存储config数据			最大20K
		if(saveData == NULL) 
			LogPrint(LOG_ERROR,__FILE__,__FUNCTION__,__LINE__,"recv buf malloc fail");
		memset(saveData,0,strlen(saveData));	
		// 插入tcp_config标志位，后续不通过http获取默认配置数据
		sprintf(saveData, "tcp_config");
		sprintf(saveData + strlen(saveData),"%s",buf);
		// 	获取上位机发送的数据
		do{
				memset(buf, 0, strlen(buf));
				recv(client_socket,buf,1460,0);	
				memcpy(saveData + strlen(saveData), buf, strlen(buf));
			}while(buf[1] != 0 && buf[1459] != 0);
		
		// 删除当前文件，写入新文件
		DeleteDirFile("device.txt");
		write_file("device.txt",saveData,strlen(saveData));// 储存到flash 不用判断失败
		// 释放结构体
		myfree(SRAMEX, get->device_params->params->gateway_read_dlt645_command);
		get->device_params->params->gateway_read_dlt645_command = NULL;
		myfree(SRAMEX, get->device_params->params->gateway_read_modbus_command);
		get->device_params->params->gateway_read_modbus_command = NULL;
		myfree(SRAMEX, get->device_params->params->gateway_write_modbus_command);
		get->device_params->params->gateway_write_modbus_command = NULL;
		myfree(SRAMEX, get->device_params->params);
		get->device_params->params = NULL;
		myfree(SRAMEX, get->device_params);
		get->device_params = NULL;
		get = NULL;
		// 重新解析config数据
		addGatewayParams(saveData);
		myfree(SRAMEX, saveData);
		
		char* retMsg = mymalloc(SRAMEX,32);
		memset(retMsg, 0, strlen(retMsg));
		retMsg = "{\"write_config\":\"success\"}";
		send(client_socket, retMsg, strlen(retMsg), 0);	
		myfree(SRAMEX ,retMsg);
}
// 储存上位机发送的config_add数据，并返回上位机操作结果
void add_config(int client_socket, char* dataBuf)
{	
	GATEWAY_PARAMS *get;
	get= get_gateway_config_params();
	DEVICE_PARAMS *device=get->device_params;
	char* retMsg = mymalloc(SRAMEX,32);
	memset(retMsg, 0, strlen(retMsg));
	while(device != NULL)// 一直轮询到当前为NULL
	{
		device = device->nextDevice;
	}
	addDevice(dataBuf);
	// 再检查更新后的deviceId是否为NULL
	if(device == NULL)// error
	{	
		retMsg = "{\"write_config\":\"error\"}";
		send(client_socket, retMsg, strlen(retMsg), 0);	
	}
	else// success
	{
		retMsg = "{\"write_config\":\"success\"}";
		send(client_socket, retMsg, strlen(retMsg), 0);	
	}
		myfree(SRAMEX, retMsg);
}
// 设备嗅探
void find_device(int client_socket)
{
	char deviceId[50];// 发送设备名
	GATEWAY_PARAMS *get;
	get= get_gateway_config_params();
	if(get->device_params == NULL)
	{	
		sprintf(deviceId, "{\"find_device\":\"%s\"}", gatewayId);		
		send(client_socket, deviceId, strlen(deviceId), 0);
	}
	else
	{
		sprintf(deviceId, "{\"find_device\":\"%s\"}", get->deviceId);		
		send(client_socket, deviceId, strlen(deviceId), 0);
	}
	memset(deviceId, 0, 50);
}

// 发送设备当前的config数据
void send_config(int client_socket)
{
	GATEWAY_PARAMS *get;
	get= get_gateway_config_params();
	char* device_params = mymalloc(SRAMEX, 3 * 1024);
	memset(device_params,0,3 * 1024);
	if(get->device_params == NULL)
	{
		sprintf(device_params, "{\"read_config\":\"error\"}");
		send(client_socket, device_params, strlen(device_params), 0);
	}
	else
	{
		get_device_params(device_params);
		send(client_socket, device_params, strlen(device_params), 0);
	}
	myfree(SRAMEX, device_params);
}

// 解析上位机发送的ip_config数据
void analysis_ip_config(int client_socket, int sockfd,struct sockaddr_in tcpServerSock, char* buf)
{
		// 打开DHCP
		if (strstr(buf, "\"dhcpMode\":\"open\"") != NULL)
		{
//#ifdef USE_DHCP
			DHCP_open();	
//#endif			
			char* retMsg = mymalloc(SRAMEX,32);
			retMsg = "{\"ip_config\":\"success\"}";
			send(client_socket,retMsg,strlen(retMsg),0);
			myfree(SRAMEX, retMsg);
		}
		// 关闭DHCP
		else if (strstr(buf, "\"dhcpMode\":\"close\"") != NULL)
		{		
			uint8_t prot[6];
			// 设置静态IP地址，并关闭DHCP
			set_ipaddr(buf);
			// 解析buf内的数据，保存到load_ip_config结构体
			parseStringField(buf, "\"ipv4\":\"", (char *)&load_ip_config.host);// eg:192.168.1.100
			parseStringField(buf, "\"subnetMask\":\"", (char *)&load_ip_config.subnetMask);// eg:255.255.255.0
			parseStringField(buf, "\"defaultGateway\":\"", (char *)&load_ip_config.defaultGateway);// eg:192.168.1.1
			parseStringField(buf, "\"udpLogPort\":\"", (char *)&prot);
			load_ip_config.udpLogPort = atoi((char *)&prot);
			// 关闭服务端和客户端
			lwip_close(sockfd);	
			lwip_close(client_socket);
			// DHCP关闭标志位置 1 
			closeFlag = 1;
		}
}

// 切换工作模式
void work_mode(char* buf)
{
	/* 用标志位开关data_task任务中，发送数据的方式 */
		// 内置协议模式
		if(strstr(buf,"protocolsMode") != NULL)
		{
			ProtocolsModeFlag = 1;// 开启内置协议模式
			TransparentModeFlag = 0; // 关闭透明传输模式
			LogPrint(LOG_INFO,__FILE__,__FUNCTION__,__LINE__,"ProtocolsMode");	
		}
		// 透明传输模式
		if(strstr(buf,"TransparentMode") != NULL)
		{
			ProtocolsModeFlag = 0;// 关闭内置协议模式
			TransparentModeFlag = 1; // 开启透明传输模式
			LogPrint(LOG_INFO,__FILE__,__FUNCTION__,__LINE__,"TransparentModeFlag");	
		}
}
#endif
void tcp_server_task(void const * argument)
{
    int ret,sockfd;
		int recv_size;
    struct sockaddr_in tcpServerSock;
    struct sockaddr_in client_sock;
		// 命令集
		char* recv_cmd[] = {"\"cmd\":\"write_config\"","\"cmd\":\"write_config_add\"",
												"\"cmd\":\"read_config\"","\"cmd\":\"find_device\"",
												"\"cmd\":\"ip_config\"","\"cmd\":\"toggle_work_mode\"",
												"\"cmd\":\"software_update\"","\"cmd\":\"reboot\""};

#ifdef USE_DHCP										
		while(dhcp_done!=1)	{vTaskDelay(100);}
#endif

    tcpServerSock.sin_family = AF_INET;
		inet_aton("192.168.0.3",&(tcpServerSock.sin_addr));
//    tcpServerSock.sin_addr.s_addr = htonl(IPADDR_ANY);
    tcpServerSock.sin_port = htons(8080);
tcp_server_begin:
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        goto tcp_server_begin;
    }
    ret = bind(sockfd, (struct sockaddr *)&tcpServerSock, sizeof(tcpServerSock));
    if (ret < 0)
    {
        lwip_close(sockfd);
        sockfd = -1;
        goto tcp_server_begin;
    }
    ret = listen(sockfd, 10);
    if (ret < 0)
    {
        lwip_close(sockfd);
        sockfd = -1;
        goto tcp_server_begin;
    }
		socklen_t len = sizeof(client_sock);
    int client_socket = accept(sockfd, (struct sockaddr*)&client_sock,&len);
		if (client_socket<0)
    {
      printf("error");
    }
		LogPrint(LOG_INFO,__FILE__,__FUNCTION__,__LINE__,"PC connect success");	
    while (1)
    {		
				vTaskDelay(100);

				char *dataBuf= mymalloc(SRAMEX,RECV_BUF_SIZE);// 存储上位机下发数据			
				
				memset(dataBuf,0,RECV_BUF_SIZE);
				// 	获取上位机发送的数据
				recv_size=recv(client_socket,dataBuf,RECV_BUF_SIZE,0);

					// 接收到消息
					// 解析上位机发送的CMD命令	
					if(recv_size>0)
					{
						int j = 0;
						for(int i = 0; i < sizeof(recv_cmd)/sizeof(recv_cmd[0]); i++)
						{
							if(strstr(dataBuf,recv_cmd[i]) != NULL)
							{
								i = sizeof(recv_cmd)/sizeof(recv_cmd[0]);
							}
							j++;
						}
						
						if (ProtocolsModeFlag) {
								switch (j) {
									case WRITE_CONFIG:
											LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "write config");
											save_config(client_socket, dataBuf);
											break;
									case WRITE_CONFIG_ADD:
											add_config(client_socket, dataBuf);
											LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "write config add");
											break;
									case READ_CONFIG:
											send_config(client_socket);
											LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "read config");
											break;
									case FIND_DEVICE:
											find_device(client_socket);
											LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "find device");
											break;
									case IP_CONFIG:
											LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "ipconfig");
											analysis_ip_config(client_socket, sockfd, tcpServerSock, dataBuf);
											if (closeFlag == 1) {
													// 更新新的地址
													inet_aton((char*)&load_ip_config.host, &(tcpServerSock.sin_addr));
													closeFlag = 0;
													goto tcp_server_begin;
											}
											break;
									case TOGGLE_MODE:
											work_mode(dataBuf);
											LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "toggle work mode");
											break;
									case UPDATE:
											LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "update");
											updata_task_creat(client_socket);
											break;
									case REBOOT:
											send(client_socket,"{\"reboot\":\"success\"}", 20, 0);
											LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "reboot");
											__set_PRIMASK(1);
											NVIC_SystemReset();
											break;
								}
							} else {
								switch (j) {
									case FIND_DEVICE:
											find_device(client_socket);
											LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "find device");
											break;
									case IP_CONFIG:
											LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "ip config");
											analysis_ip_config(client_socket, sockfd, tcpServerSock, dataBuf);
											if (closeFlag == 1) {
													// 更新新的地址
													inet_aton((char*)&load_ip_config.host, &(tcpServerSock.sin_addr));
													closeFlag = 0;
													goto tcp_server_begin;
											}
											break;
									case TOGGLE_MODE:
											work_mode(dataBuf);
											LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "toggle work mode");
											break;
									case UPDATE:
											LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "update");
											updata_task_creat(client_socket);
											break;
									case REBOOT:
											send(client_socket,"{\"reboot\":\"success\"}", 20, 0);
											LogPrint(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, "reboot");
											__set_PRIMASK(1);
											NVIC_SystemReset();	
											break;
							}
						}
					}
					// 没接收到消息
					else if(recv_size==0)
					{
						lwip_close(client_socket);
						LOG_PRINT(LOG_ERROR,"PC disconnect,wait reconnect");
						client_socket= accept(sockfd, (struct sockaddr*)&client_sock,&len);
					}
					myfree(SRAMEX, dataBuf);
			}
}
/*!
    \brief      initialize the tcp_client application
    \param[in]  none
    \param[out] none
    \retval     none
*/
void tcp_server_init(void)
{
  osThreadDef(SERVER, tcp_server_task, osPriorityNormal, 0, configMINIMAL_STACK_SIZE*8);
  osThreadCreate(osThread(SERVER), NULL);
}
