#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_data_handle.h"
#include "kk_opcode.h"
#include "com_api.h"
#include "kk_data_mng.h"
const char DM_MSG_TO_MIDDWARE[] = "{\"msgtype\":\"%s\",\"productCode\":\"%s\",\"deviceCode\":\"%s\"}";
char *strrpl(char *in, char *out, int outlen, char *src, char *dst)
{
    char *p = in;
    unsigned int  len = outlen - 1;
 
    // 这几段检查参数合法性
    if((NULL == src) || (NULL == dst) || (NULL == in) || (NULL == out))
    {
        return NULL;
    }
    if((strcmp(in, "") == 0) || (strcmp(src, "") == 0))
    {
        return NULL;
    }
    if(outlen <= 0)
    {
        return NULL;
    }
 
    while((*p != '\0') && (len > 0))
    {
        if(strncmp(p, src, strlen(src)) != 0)
        {
            int n = strlen(out);
 
            out[n] = *p;
            out[n + 1] = '\0';
 
            p++;
            len--;
        }
        else
        {
            strcat(out, dst);
            p += strlen(src);
            len -= strlen(dst);
        }
    }
    return out;
}
static char * _kk_data_create(char *msgtype,const char *productCode,const char *deviceCode,const char *param)
{
	cJSON *root;
    cJSON *payload;
    cJSON* infoObj;
	char *out;
	char *infoStr = NULL;
	int infoStr_len = 0;
	int res = 0;
    char method[128] = {0};

    strrpl(msgtype+1,method,sizeof(method),"/",".");
    printf("method:%s\n",method);
	infoStr_len = strlen(DM_MSG_TO_MIDDWARE)+strlen(productCode)+strlen(deviceCode)+strlen(msgtype)+10;
	infoStr = malloc(infoStr_len);
	if(infoStr == NULL){
		ERROR_PRINT("[%s][%d]\n",__FUNCTION__,__LINE__);
		return NULL;
	}
	memset(infoStr,0x0,infoStr_len);
	snprintf(infoStr,infoStr_len,DM_MSG_TO_MIDDWARE,msgtype,productCode,deviceCode);

	root=cJSON_CreateObject();
    infoObj = cJSON_Parse(infoStr);
    cJSON_AddItemToObject(root, MSG_INFO_STR, infoObj);

    payload = cJSON_CreateObject();
    if(payload){
        cJSON_AddItemToObject(root, MSG_PAYLOAD_STR, payload);	
        cJSON_AddStringToObject(payload, "msgId", "*");
        cJSON_AddStringToObject(payload, "version", "1.0");
        cJSON_AddStringToObject(payload, "method", method);
        cJSON_AddStringToObject(payload, "params", param);
    }
	out=cJSON_Print(root);
	cJSON_Minify(out);
	cJSON_Delete(root);
	free(infoStr);
	INFO_PRINT("[out]%s\n",out);	
	
	return out;
	//free(out);	/* Print to text, Delete the cJSON, print it, release the string. */
}
static void kk_handle_sync_info(void)
{
    char *send_data = NULL;
    send_data  = _kk_data_create(SYNC_MSG_TYPE,"*","*","*");
    if(send_data == NULL){
		return;
	}
	kk_ipc_send(IPC_APP2MID, send_data, strlen(send_data)+1);
	free(send_data);
}
static int kk_send_ack(cJSON *root,int sockfd)
{
    char *out = NULL;
    char *tmpBuf = NULL;   
    out=cJSON_Print(root);
    cJSON_Minify((char*)out);
    tmpBuf = calloc(strlen(out) + 4,1);
    if(tmpBuf == NULL){
        cJSON_Delete(root);
        free(out);
        return -1;
    }
    strcat(tmpBuf,"!");
    strcat(tmpBuf,out);
    strcat(tmpBuf,"$");
    printf("tmpBuf:%s\n",tmpBuf);
    send(sockfd, tmpBuf, strlen(tmpBuf), 0);
    cJSON_Delete(root);
    free(out);
    free(tmpBuf);   
    return 0; 
}
static int _kk_send_data_to_sdk(char *nodeid,char *opcode,char *arg)
{
    cJSON *root;
    char *out = NULL;
    root=cJSON_CreateObject();
    if(root){
        cJSON_AddStringToObject(root, "nodeid", nodeid);
        cJSON_AddStringToObject(root, "opcode", opcode);
        cJSON_AddStringToObject(root, "status", "success");
        cJSON_AddStringToObject(root, "arg", arg);
        out=cJSON_Print(root);
        printf("[%s][%d]\n",__FUNCTION__,__LINE__);
        printf("out:%s\n",out);
        cJSON_Minify((char*)out);
        kk_send_data_to_sdk(out);
    }
    free(arg);
    cJSON_Delete(root);
    return 0;
}
static int kk_heartbeat_ack(int sockfd)
{
    cJSON *root;
    root=cJSON_CreateObject();
    if(root){
        cJSON_AddStringToObject(root, "nodeid", "*");
        cJSON_AddStringToObject(root, "opcode", HEARTBEAT_OPCODE);
        cJSON_AddStringToObject(root, "status", "success");
        cJSON_AddStringToObject(root, "arg", "*");
        kk_send_ack(root,sockfd);
    }
    cJSON_Delete(root);
    return 0;
}
static int kk_loginccu_ack(cJSON *arg,int sockfd)
{
    cJSON *zkid;
    cJSON *root;
    cJSON *args;
    char *out = NULL;
    char *tmpBuf = NULL;    
    if(arg == NULL){
        return -1;
    }
    zkid = cJSON_GetObjectItem(arg, ZKID_STRING);
    if(zkid != NULL){
        if(strstr(KK_CCU_ID,zkid->valuestring) != NULL){
            root=cJSON_CreateObject();
            if(root){
                args = cJSON_CreateObject();
                if(args){
                    cJSON_AddItemToObject(root, "arg", args);
                    cJSON_AddStringToObject(args, "error_code", "0");
                    cJSON_AddStringToObject(args, "seq", "");           
                    cJSON_AddStringToObject(args, "zkid", zkid->valuestring); 
                }
                cJSON_AddStringToObject(root, "nodeid", "*");
                cJSON_AddStringToObject(root, "opcode", LOGIN_OPCODE);
                cJSON_AddStringToObject(root, "status", "success");
                kk_send_ack(root,sockfd);
            }
            cJSON_Delete(root);
        }
    }else{
        ERROR_PRINT("data error...\n");
        return -1;
    }
    return 0;
}
int kk_data_handle(cJSON *json,int sockfd)
{
    cJSON *opcode;
    cJSON *arg;
    opcode = cJSON_GetObjectItem(json, OPCODE_STRING);
    if(opcode != NULL){
        if(strcmp(opcode->valuestring,LOGIN_OPCODE) == 0){
            arg = cJSON_GetObjectItem(json, ARG_STRING);
            kk_loginccu_ack(arg,sockfd);
        }else if(strcmp(opcode->valuestring,HEARTBEAT_OPCODE) == 0){
            kk_heartbeat_ack(sockfd);
        }else if(strcmp(opcode->valuestring,SYNC_OPCODE) == 0){
            kk_handle_sync_info();
        } 
    }
    return 0;

}
static int kk_parse_syncinfo(cJSON *payload)
{
    cJSON *paramStr,*dataStr;
    cJSON *gwdevices,*subdevices;
    cJSON * gwitem,*properties;  
    char *gwdevicecode;
    char *deviceCode,*productCode;
    char *identifier,*valuetype;
    cJSON * subitem;
    cJSON * newccuItem;
    cJSON *valuejson;
    int value;
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    kk_map_dev_node_t *node = NULL;  
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    paramStr = cJSON_GetObjectItem(payload, DATA_STRING);
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    if(paramStr == NULL) return -1;	
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    dataStr = cJSON_GetObjectItem(paramStr, DATA_STRING);
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    if(dataStr == NULL) return -1;
    gwdevices = cJSON_GetObjectItem(dataStr, DEVICES_STRING);
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    if(gwdevices == NULL) return -1; 
    gwitem = gwdevices->child;
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    while(gwitem != NULL){
        printf("[%s][%d]\n",__FUNCTION__,__LINE__);
        subdevices = cJSON_GetObjectItem(gwitem,DEVICES_STRING);
        gwdevicecode = cJSON_GetObjectItem(gwitem,MSG_DEVICE_CODE_STR)->valuestring;
        if(subdevices != NULL){
            printf("[%s][%d]\n",__FUNCTION__,__LINE__);
            subitem = subdevices->child;
            while(subitem != NULL){
                printf("[%s][%d]\n",__FUNCTION__,__LINE__);
                deviceCode = cJSON_GetObjectItem(subitem,MSG_DEVICE_CODE_STR)->valuestring;
                productCode = cJSON_GetObjectItem(subitem,MSG_PRODUCT_CODE_STR)->valuestring;
                properties = cJSON_GetObjectItem(subitem,MSG_PROPERTIES_STR);
                printf("[%s][%d]\n",__FUNCTION__,__LINE__);
                node = kk_map_dev_add(deviceCode,productCode,gwdevicecode);
                if(node != NULL && node->newccu != NULL){
                    newccuItem = node->newccu->child;
                    while(newccuItem != NULL){
                        identifier = cJSON_GetObjectItem(newccuItem,MSG_INDENTIFIER_STR)->valuestring;
                        valuetype = cJSON_GetObjectItem(newccuItem,MSG_INDENTIFIER_STR)->valuestring;
                        valuejson = cJSON_GetObjectItem(properties,identifier);
                        if(valuejson != NULL){
                            if(strcmp(valuetype,"bool") == 0 || strcmp(valuetype,"int") == 0){
                                value = valuejson->valueint;
                                printf("[%s][%d]\n",__FUNCTION__,__LINE__);
                                kk_map_dev_update_int_value(node,identifier,value);
                            }
                        }
                        newccuItem = newccuItem->next;
                    }
                }
                subitem = subitem->next;
            }
        }
        gwitem = gwitem->next;
    }
    return 0;
}
static int kk_create_floors_to_sdk(cJSON *root)
{
    cJSON *floors = cJSON_CreateArray();
    cJSON *floorItem = cJSON_CreateObject();
    cJSON_AddStringToObject(floorItem, "floor_icon", "");
    cJSON_AddStringToObject(floorItem, "floor_pos", "1");
    cJSON_AddStringToObject(floorItem, "id", "1");
    cJSON_AddStringToObject(floorItem, "name", "一楼");
    cJSON_AddItemToArray(floors, floorItem);
    cJSON_AddItemToObject(root, "floors", floors);
    return 0;
}
static int kk_create_roominfo_to_sdk(cJSON *root)
{
    cJSON *rooms = cJSON_CreateArray();
    cJSON *roomsItem = cJSON_CreateObject();
    cJSON *room_status;
    cJSON_AddStringToObject(roomsItem, "floor_id", "1");
    cJSON_AddStringToObject(roomsItem, "id", "1");
    cJSON_AddStringToObject(roomsItem, "room_icon", "");
    cJSON_AddStringToObject(roomsItem, "name", "卧室");
    room_status = cJSON_CreateObject();
    cJSON_AddItemToObject(roomsItem, "room_status", room_status);
    cJSON_AddItemToArray(rooms, roomsItem);
    cJSON_AddItemToObject(root, "rooms", rooms);
    return 0;
}
static int kk_create_scene_to_sdk(cJSON *root)
{
    cJSON *scenes = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "scenes", scenes);
    return 0;
}
int kk_create_syncinfo_to_sdk(void)
{
    cJSON *air_box_devices;
    cJSON *alarms;
    cJSON *ccu_link_status;
    cJSON *link_arg;
    cJSON *ccu_version;
    cJSON *central_ac_gws;
    cJSON *central_ac_indoorunits;
    cJSON *cnwise_music_controllers;
    cJSON *code_lib_controllers;
    cJSON *controllers;
    cJSON *expand_rules;
    cJSON *group;
    cJSON *guard;
    cJSON *gw_version;
    char *out = NULL;
    cJSON *root=cJSON_CreateObject();
    cJSON *aiks_controllers = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "aiks_controllers", aiks_controllers);
    air_box_devices = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "air_box_devices", air_box_devices);
    alarms = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "alarms", alarms); 
    ccu_link_status = cJSON_CreateObject(); 
    link_arg = cJSON_CreateObject(); 
    cJSON_AddItemToObject(ccu_link_status, "link_arg", link_arg);  
    cJSON_AddStringToObject(ccu_link_status, "link_type", "broadband_net");  
    cJSON_AddItemToObject(root, "ccu_link_status", ccu_link_status);
    ccu_version = cJSON_CreateObject();
    cJSON_AddStringToObject(ccu_version, "cur_ccu_version", "1.0.0"); 
    cJSON_AddStringToObject(ccu_version, "downloaded_ccu_version", "1.0.0"); 
    cJSON_AddItemToObject(root, "ccu_version", ccu_version);
    central_ac_gws = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "central_ac_gws", central_ac_gws);
    central_ac_indoorunits = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "central_ac_indoorunits", central_ac_indoorunits);    
    cnwise_music_controllers = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "cnwise_music_controllers", cnwise_music_controllers);       
    code_lib_controllers = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "code_lib_controllers", code_lib_controllers);     
   
    controllers = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "controllers", controllers);  
 
    kk_create_devicestatus_to_sdk(root);
   
    kk_create_devices_to_sdk(root);
     #if 1 
     printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    expand_rules = cJSON_CreateArray();
     printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    cJSON_AddItemToObject(root, "expand_rules", expand_rules);  
     printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    kk_create_floors_to_sdk(root);
    group = cJSON_CreateArray();
     printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    cJSON_AddItemToObject(root, "group", group); 
     printf("[%s][%d]\n",__FUNCTION__,__LINE__);   
    guard = cJSON_CreateObject();
    cJSON_AddItemToObject(root, "guard", guard);        
    gw_version = cJSON_CreateObject();
     printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    cJSON_AddItemToObject(root, "gw_version", gw_version);  
     printf("[%s][%d]\n",__FUNCTION__,__LINE__); 
    kk_create_roominfo_to_sdk(root);   
     printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    kk_create_scene_to_sdk(root);  
    #endif
     printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    out=cJSON_Print(root);
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    printf("out:%s\n",out);
    cJSON_Minify((char*)out);
    _kk_send_data_to_sdk("*","*",out);
    return 0;          
}
void KK_Data_FromMid(void* str,int len)
{
    cJSON *json;
    cJSON *info_root;
    cJSON *payload,*typeJson;

	printf("str:%s\n",str);

    json = cJSON_Parse(str);
    if(json == NULL){
        return;
    }
    info_root = cJSON_GetObjectItem(json, MSG_INFO_STR);
	if(info_root == NULL) return;
    payload = cJSON_GetObjectItem(json, MSG_PAYLOAD_STR);
    if(payload == NULL) return;    
	typeJson = cJSON_GetObjectItem(info_root, MSG_TYPE_STR);
	if(typeJson == NULL) return;
    if (strstr(typeJson->valuestring,SYNC_MSG_TYPE_REPLY) != NULL){
        kk_parse_syncinfo(payload);
        kk_create_syncinfo_to_sdk();
    }
}