#include<stdio.h>
#include <string.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <errno.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
#include "kk_login_handle.h"
#include "kk_data_handle.h"
#include "kk_lan_debug.h"

#define LISTEN_MAX 16
#define BUF_SIZE 1500

typedef struct {
	int socketfd;
	char ip[18];
} kk_clientInfo_t;
static kk_clientInfo_t s_ConnInfo[LISTEN_MAX] = {0};
static pthread_mutex_t data_mutex;
fd_set fds;


void tcp_data_mutex_lock(void)
{
	pthread_mutex_lock(&data_mutex);
}

void tcp_data_mutex_unlock(void)
{
	pthread_mutex_unlock(&data_mutex);
}


int kk_send_data_to_sdk(char *buf)
{
	char *tmpBuf = NULL;   
	int i = 0;
	tmpBuf = calloc(strlen(buf) + 4,1);
	if(tmpBuf == NULL){
		return -1;
	}
	strcat(tmpBuf,"!");
	strcat(tmpBuf,buf);
	strcat(tmpBuf,"$");
	INFO_PRINT("tmpBuf:%s\n",tmpBuf);
	for(i = 0; i < LISTEN_MAX; i++){
		tcp_data_mutex_lock();
		if(s_ConnInfo[i].socketfd != -1){
	
			send(s_ConnInfo[i].socketfd, tmpBuf, strlen(tmpBuf), 0);
	
		}
		tcp_data_mutex_unlock();
	}

	free(tmpBuf); 
	return 0;
}
static int _kk_handle_data(char *buf,int sockfd){
	char *pStart = NULL,*pEnd = NULL;
	char tmpBuf[BUF_SIZE] = {0};
	cJSON *json; 
	if(buf == NULL){
		return -1;
	}
	pStart = strstr(buf, "!");
	pEnd = strstr(buf, "$");  
	if(pStart != NULL && pEnd != NULL){
		memset(tmpBuf,0x0,sizeof(tmpBuf));
		memcpy(tmpBuf,pStart+1,(pEnd - pStart - 1));
	}
	json=cJSON_Parse(tmpBuf);
	if (!json) {
		WARNING_PRINT("Error before: [%s]\n","cJSON_Parse");
	}else{
		kk_data_handle(json,sockfd);
		cJSON_Delete(json);
	}
	return 0;
}

static void PrintMesg(int i , char buf[])
{
	printf("fd : %d, msg: %s\n", i , buf);
}

static int kk_check_is_connect(char *ip){
	int i = 0;
	if(ip == NULL){
		return -1;
	}
	for(i =  0; i < LISTEN_MAX; i ++){
		if(s_ConnInfo[i].socketfd != -1 && strcmp(s_ConnInfo[i].ip,ip) == 0){
			pthread_mutex_lock(&data_mutex);
			close(s_ConnInfo[i].socketfd);
			s_ConnInfo[i].socketfd = -1;
			memset(s_ConnInfo[i].ip,0x0,sizeof(s_ConnInfo[i].ip));
			pthread_mutex_unlock(&data_mutex);
			return 1;
		}
	}
	return 0;
}
void *TCPServer()
{
	struct sockaddr_in Server;
	struct sockaddr_in Client;
	int Listenfd = -1;
	int client_fd = -1;
	int i = 0;
	int j = 0;
	int yes = 1;
	int index = 0;
	int ret = 0;
	char clientIp[18] = {0};
	int max_fd = 0;
	socklen_t len = 0;
	fd_set server_fd_set;
	struct timeval time_out;
	char Buf[BUF_SIZE] = {0};

	Listenfd = socket(AF_INET, SOCK_STREAM, 0);
	if (Listenfd < 0)
	{
		perror("socket");
		return NULL;
	}
	DEBUG_PRINT("TCPServer:create socket success\n");
	setsockopt(Listenfd, SOL_SOCKET, SO_REUSEADDR, &yes ,sizeof(int));// 允许IP地址复用
	bzero(&Server, sizeof(Server));
	Server.sin_family = AF_INET;
	Server.sin_port = htons(SERVER_LISTEN_PORT);
	Server.sin_addr.s_addr = htonl(INADDR_ANY);

	if (bind(Listenfd, (struct sockaddr*)&Server, sizeof(Server)) < 0)
	{
		perror("bind");
		close(Listenfd);
		return NULL;
	}
	DEBUG_PRINT("TCPServer:bind socket success\n");

	if (listen(Listenfd, LISTEN_MAX) < 0)
	{
		perror("listen");
		close(Listenfd);
		return NULL;
	}
	DEBUG_PRINT("TCPServer:listen socket success\n");
	while (1)
	{
		//index = -1;
		max_fd = client_fd > Listenfd?client_fd:Listenfd;
		time_out.tv_sec = 1;//select会更改timeout的值，所以需要重新初始化超时时间
		time_out.tv_usec = 0;
		FD_ZERO(&server_fd_set);
		FD_SET(Listenfd,&server_fd_set);
		for(i=0;i<LISTEN_MAX;i++)
		{
			pthread_mutex_lock(&data_mutex);
			if(s_ConnInfo[i].socketfd>0)
			{
				FD_SET(s_ConnInfo[i].socketfd,&server_fd_set);
			}
			pthread_mutex_unlock(&data_mutex);
		}
		ret = select(max_fd + 1, &server_fd_set,NULL, NULL, &time_out );
		if(ret <= 0){
			//INFO_PRINT("TCPServer:TCP receiving nothing......\n");
			//break;
		}else{
			if (FD_ISSET(Listenfd, &server_fd_set))
			{
				len = sizeof(Client);
				bzero(&Client, len);
				client_fd = accept(Listenfd, (struct sockaddr*)&Client,&len );
				INFO_PRINT("addr:%s\n",inet_ntoa(Client.sin_addr));
				INFO_PRINT("[%s][%d]Connfd:%d\n",__FUNCTION__,__LINE__,client_fd);
				//若有新的连接
				if (client_fd != -1)
				{
					memset(clientIp,0x0,sizeof(clientIp));
					strcpy(clientIp,inet_ntoa(Client.sin_addr));
					if(kk_check_is_connect(clientIp) == 1){
						DEBUG_PRINT("already connect!!!\n");
						//continue;
					}
					for(i =  0; i < LISTEN_MAX; i ++){
						if(s_ConnInfo[i].socketfd != -1){
							if(i == LISTEN_MAX-1){
								DEBUG_PRINT("more then max client!!!\n");
								break;
							}
							continue;
						}else{
							pthread_mutex_lock(&data_mutex);
							s_ConnInfo[i].socketfd = client_fd;
							memcpy(s_ConnInfo[i].ip,clientIp,strlen(clientIp));
							index = i;
							pthread_mutex_unlock(&data_mutex);
							break;
						}
					}

				}
			}else{
				for(i=0;i<LISTEN_MAX;i++)
				{
					if(s_ConnInfo[i].socketfd==-1){
						continue ;
					}
					if(FD_ISSET(s_ConnInfo[i].socketfd,&server_fd_set))
					{
						
						memset(Buf,0,sizeof(Buf));
						pthread_mutex_lock(&data_mutex);
						ret = recv(s_ConnInfo[i].socketfd,Buf,sizeof(Buf), 0);//最后一个参数为0，表示默认阻塞接收,前面select解除了阻塞说明有数据可读
						pthread_mutex_unlock(&data_mutex);
						
						if(ret > 0)
						{
							INFO_PRINT("recv->buf:%s\n",Buf);
							_kk_handle_data(Buf,s_ConnInfo[i].socketfd);
						}
						else
						{
							INFO_PRINT("client disconnected\r\n");
							pthread_mutex_lock(&data_mutex);
							close(s_ConnInfo[i].socketfd);
							s_ConnInfo[i].socketfd = -1;
							memset(s_ConnInfo[i].ip,0x0,sizeof(s_ConnInfo[i].ip));
							pthread_mutex_unlock(&data_mutex);
						}
					}
				}			
			}
		}
	}
	FD_CLR(Listenfd, &fds);// 清除 fds中相应的文件描述符
	close(Listenfd);
	
	
	return NULL;
}

int kk_login_init()
{
	int ret = 0;
	int i = 0;
	pthread_t threadID = 0;

	DEBUG_PRINT("kk_login_init Init OK!\n");

	if (pthread_mutex_init(&data_mutex, NULL) != 0) {
		ERROR_PRINT("pthread_mutex_init kk_login_init err\n");
		return -1;
	}

	pthread_mutex_lock(&data_mutex);
	for(i =  0; i < LISTEN_MAX; i ++){
		s_ConnInfo[i].socketfd = -1;
		memset(s_ConnInfo[i].ip,0x0,sizeof(s_ConnInfo[i].ip));
	}
	pthread_mutex_unlock(&data_mutex);
	
	pthread_attr_t attr;
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);	
	ret = pthread_create(&threadID, &attr, TCPServer, NULL);
	if(0 != ret)
	{
		ERROR_PRINT("TCPServer: TCPServer build Fail!\n");
		return -1;
	}
	pthread_attr_destroy(&attr);//线程属性销毁	
	return 0;
}
