
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <time.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include "kk_findccu_handle.h"
#include "kk_hal.h"
#include "cJSON.h"

static int kk_findccu_ack(int sockfd,struct sockaddr_in *addr){
    cJSON *json = NULL,*args = NULL;
    cJSON *ccu = NULL;
    char *out = NULL;
    char *tmpBuf = NULL;
     char s_IP[NETWORK_ADDR_LEN] = {0};
    if(addr == NULL || sockfd < 0){
        return -1;
    }
    json=cJSON_CreateObject();
    if(json){
        args = cJSON_CreateObject();
        if(args){
            cJSON_AddItemToObject(json, "arg", args);
            cJSON_AddStringToObject(args, "zkid", KK_CCU_ID);
            cJSON_AddStringToObject(args, "zk", KK_CCU_NAME);           
            HAL_Get_IP(s_IP,NULL);
            cJSON_AddStringToObject(args, "ip", s_IP); 
            cJSON_AddBoolToObject(args, "ssl", FALSE);
        }
        cJSON_AddStringToObject(json, "nodeid", "*");
        cJSON_AddStringToObject(json, "opcode", FINDCCU_OPCODE);
        cJSON_AddStringToObject(json, "status", "success");
        out=cJSON_Print(json);
        cJSON_Minify((char*)out);
        tmpBuf = calloc(strlen(out) + 4,1);
        if(tmpBuf == NULL){
            cJSON_Delete(json);
            free(out);
            return -1;
        }
        strcat(tmpBuf,"!");
        strcat(tmpBuf,out);
        strcat(tmpBuf,"$");
        printf("tmpBuf:%s\n",tmpBuf);
        sendto(sockfd, tmpBuf, strlen(tmpBuf), 0, (struct sockaddr*)addr, sizeof(struct sockaddr_in));
        cJSON_Delete(json);
        free(out);
        free(tmpBuf);
    }
    return 0;
}
void *kk_findccu_handle(void *data)
{
	int sockfd;
	struct sockaddr_in saddr;
	int r;
	char recvline[1025] = {0};
    char recvline_tmp[1025] = {0};
	struct sockaddr_in presaddr;
	socklen_t len;
    cJSON *json;
    cJSON *opcode;
    char *pStart = NULL,*pEnd = NULL;
	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	bzero(&saddr, sizeof(saddr));
    
	saddr.sin_family = AF_INET;
	saddr.sin_addr.s_addr = htonl(INADDR_ANY);
	saddr.sin_port = htons(FINDCCU_LOCAL_PORT);
	
    if(bind(sockfd, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) 
    { 
        ERROR_PRINT("bind error...\n"); 
    } 
	while (1)
	{
		r = recvfrom(sockfd, recvline, sizeof(recvline), 0 , (struct sockaddr*)&presaddr, &len);
		if (r <= 0){
            WARNING_PRINT("read error....\n"); 
		}else{
            DEBUG_PRINT("findccu recmsg: %s\n", recvline); 
            pStart = strstr(recvline, "!");
            pEnd = strstr(recvline, "$");
            if(pStart != NULL && pEnd != NULL){
                memset(recvline_tmp,0x0,sizeof(recvline_tmp));
                memcpy(recvline_tmp,pStart+1,(pEnd - pStart - 1));
                json=cJSON_Parse(recvline_tmp);
                if (!json) {
                    WARNING_PRINT("Error before: [%s]\n","cJSON_Parse");
                }else{
                    opcode = cJSON_GetObjectItem(json, OPCODE_STRING);
                    if(opcode != NULL){
                        if(strcmp(opcode->valuestring,FINDCCU_OPCODE) == 0){
                            kk_findccu_ack(sockfd,&presaddr);
                        }
                    }
                    cJSON_Delete(json);
                }
            }else{
                WARNING_PRINT("data error....\n"); 
            }
        }

	}
    return NULL;
}

int kk_findccu_handle_init(void)
{
    int rc = 0;
    size_t s = 1500;
    pthread_t findccu_thread_handle;
    pthread_attr_t findccu_thread_attr;
    //pthread_mutex_init(&s_data_mutex, NULL);
    /*创建线程*/
    pthread_attr_init(&findccu_thread_attr);
    pthread_attr_setstacksize(&findccu_thread_attr, s);
    pthread_attr_setdetachstate(&findccu_thread_attr, PTHREAD_CREATE_DETACHED);
    rc = pthread_create(&findccu_thread_handle, &findccu_thread_attr, kk_findccu_handle, (void *)NULL);   //收数据
    if (rc)
    {
        WARNING_PRINT("Error : unable to create thread udp_recv \r\n");
        return -1;
    }
    pthread_attr_destroy(&findccu_thread_attr);
    return 0;
}