
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "kk_data_mng.h"

static kk_map_dev_ctx g_map_dev_mgr = {0};
static kk_map_dev_ctx *_kk_map_dev_ctx(void)
{
    return &g_map_dev_mgr;
}

static void _kk_map_dev_mutex_lock(void)
{
    kk_map_dev_ctx *ctx = _kk_map_dev_ctx();
    if (ctx->mutex) {
        kk_MutexLock(ctx->mutex);
    }
}
static void _kk_map_dev_mutex_unlock(void)
{
    kk_map_dev_ctx *ctx = _kk_map_dev_ctx();
    if (ctx->mutex) {
        kk_MutexUnLock(ctx->mutex);
    }
}
int kk_map_dev_init(void)
{
    kk_map_dev_ctx *ctx = _kk_map_dev_ctx();
    memset(ctx, 0, sizeof(kk_map_dev_ctx));
    ctx->mutex = kk_MutexCreate(); 
    if (ctx->mutex == NULL) {
        return -1;
    }
    INIT_LIST_HEAD(&ctx->dev_list);
    return 0;
}
static int kk_open_cfg_file(char *deviceCode,kk_map_dev_node_t *node)
{
    char path[128] = {0};
    unsigned int filesize;
    FILE *fp;
    char *buf = NULL;
    cJSON *json = NULL;
    cJSON *optype = NULL;
    sprintf(path,KK_DEVICE_MAP_FILE_PATH,deviceCode);
    printf("kk_open_cfg_file path:%s\n",path);
	if(!(fp =  fopen(path,"r")))
	{
		ERROR_PRINT("can't open the file tslPath:%s\n",path);
		return -1;
	}
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    fseek(fp, 0L, SEEK_END);
    filesize = ftell(fp);	
	buf = malloc(filesize+1);
	if(buf == NULL)
	{
		ERROR_PRINT("MALLOC FAIL!!!\n");
        fclose(fp);
		return -1;
	}
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
	memset(buf,0x0,filesize+1);
	fseek(fp, 0L, SEEK_SET);
	fread(buf, 1, filesize, fp);  
    printf("buf:%s\n",buf);
    json = cJSON_Parse(buf);  
    if(json == NULL){
        ERROR_PRINT("cJSON_Parse FAIL!!!\n");
        free(buf);
        fclose(fp);
		return -1;
    }
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    optype = cJSON_GetObjectItem(json, OPEARTETYPE_STRING);
    if(optype != NULL){
        memcpy(node->opearteType,optype->valuestring,strlen(optype->valuestring));
    }
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    node->channelNum = cJSON_GetObjectItem(json, CHANNEL_STRING)->valueint;
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    node->newccu = cJSON_GetObjectItem(json, NEWCCU_STRING);
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    node->oldccu = cJSON_GetObjectItem(json, OLDCCU_STRING);
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    if(node->newccu == NULL || node->oldccu == NULL){
        ERROR_PRINT("cJSON_Parse DATA FAIL!!!\n");
        free(buf);
        fclose(fp);
		return -1;
    }
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    free(buf);
    fclose(fp);
    return 0;

}
static int kk_creater_nodeid(char *deviceCode,char *channel,char *nodeId)
{
    if(deviceCode == NULL || channel == NULL || nodeId == NULL){
        return -1;
    }
    strcat(nodeId,deviceCode);
    strcat(nodeId,"_");
    strcat(nodeId,channel);
    printf("nodeId:%s\n",nodeId);
    return 0;
}
static char* kk_value_int_map_string(char *opcodemap,kk_map_dev_node_t *node,int idx)
{
    if(opcodemap == NULL || node == NULL){
        return -1;
    }
     cJSON * oldccuItem = node->oldccu->child;
     while(oldccuItem != NULL){
         char *opcode = cJSON_GetObjectItem(oldccuItem,OPCODE_STRING)->valuestring;
         char *dataType = cJSON_GetObjectItem(oldccuItem,DATATYPE_STRING)->valuestring;
         if(strcmp(opcode,opcodemap) == 0){
             cJSON *range = cJSON_GetObjectItem(oldccuItem,VALUERANGE_STRING);
             if(range != NULL){
                 cJSON * pSub = cJSON_GetArrayItem(range, idx);
                 if(pSub != NULL){
                    if(strcmp(dataType,"string") == 0){
                        return pSub->valuestring;
                    }
                 }
             }
             
         }

     }
    return "";

}
static int kk_get_int_value_idx(cJSON * range,int val)
{
    int i = 0;
    int  array_size  = cJSON_GetArraySize (range);
    for(i = 0; i < array_size; i++){
        cJSON * pSub = cJSON_GetArrayItem(range, i);
        if(pSub != NULL && pSub->valueint == val){
            return i;
        }
    }
    return -1;
}
static int _deviceCode_switchto_mac(char * deviceCode,char *mac)
{
    char deviceCode_bak[33] = {0};
    int i, j;
    int len =  strlen(deviceCode);
    for(i=0; i < len; i++)  /*将串s拷贝至串t*/
        deviceCode_bak[i]=deviceCode[i];
    deviceCode_bak[i]='\0';
    for(i=0,j=0; i < len; i++){
        if( i % 2 == 0 && i != 0)
        {
            mac[j++]=':';
            mac[j++]=deviceCode_bak[i];
        }
        else
        {
            mac[j++]=deviceCode_bak[i];
        }
    }
    mac[j]='\0';  /*在串s结尾加结束标志*/
    return 0;
}
int kk_create_devices_to_sdk(cJSON *root)
{
    kk_map_dev_node_t *node = NULL;
    char nodeid[32] = {0};
    char channel[4] = {0};
    char gwmac[32] = {0};
    char submac[32] = {0};
    int idx = 1;
    kk_map_dev_ctx *ctx = _kk_map_dev_ctx();
    cJSON *devices = cJSON_CreateArray();
    list_for_each_entry(node, &ctx->dev_list, linked_list, kk_map_dev_node_t) {
        if (node != NULL) {
            for(idx = 1; idx <= node->channelNum; idx++){
                printf("[%s][%d]\n",__FUNCTION__,__LINE__);
                cJSON *subdevicesItem = cJSON_CreateObject();
                sprintf(channel,"%d",idx);
                cJSON_AddStringToObject(subdevicesItem, CHANNEL_STRING, channel);
                cJSON_AddStringToObject(subdevicesItem, DEVICE_FIELD_STRING, "");
                cJSON_AddStringToObject(subdevicesItem, DEVICE_FIELD_IDNDEX_STRING, "1");
                cJSON_AddStringToObject(subdevicesItem, DEVICE_ICON_STRING, "");
                cJSON_AddStringToObject(subdevicesItem, DEVICE_POS_STRING, "1");
                _deviceCode_switchto_mac(node->gwDeviceCode,gwmac);
                printf("gwmac:%s\n",gwmac);
                cJSON_AddStringToObject(subdevicesItem, GW_MAC_STRING, gwmac);
                _deviceCode_switchto_mac(node->deviceCode,submac);
                cJSON_AddStringToObject(subdevicesItem, MAC_STRING, submac);
                cJSON_AddStringToObject(subdevicesItem, NAME_STRING, "默认灯");
                memset(nodeid,0x0,sizeof(nodeid));
                kk_creater_nodeid(node->deviceCode,channel,nodeid);
                cJSON_AddStringToObject(subdevicesItem, NODEID_STRING, nodeid);
                cJSON_AddStringToObject(subdevicesItem, OPERATE_TYPE_STRING, node->opearteType);
                cJSON_AddStringToObject(subdevicesItem, ROOM_ID_STRING, "1");
                cJSON_AddItemToArray(devices, subdevicesItem);
            }

        }
    }
    cJSON_AddItemToObject(root, DEVICES_STRING, devices);
    return 0;
}
int kk_create_devicestatus_to_sdk(cJSON *root)
{
    kk_map_dev_node_t *node = NULL;
    char nodeid[32] = {0};
    char indxId[4] = {0};
    int idx = 1;
    kk_map_dev_ctx *ctx = _kk_map_dev_ctx();
    cJSON *device_status = cJSON_CreateArray();
    #if 1
    list_for_each_entry(node, &ctx->dev_list, linked_list, kk_map_dev_node_t) {
        if (node != NULL) {
            cJSON * newccuItem = node->newccu->child;
            while(newccuItem != NULL){
                cJSON *subdevicesItem = cJSON_CreateObject();
                memset(nodeid,0x0,sizeof(nodeid));
                
                char *opcodemap = cJSON_GetObjectItem(newccuItem,OPCODEMAP_STRING)->valuestring;
                char *channel = cJSON_GetObjectItem(newccuItem,CHANNEL_STRING)->valuestring;
                char *dataType = cJSON_GetObjectItem(newccuItem,DATATYPE_STRING)->valuestring;
                cJSON *range = cJSON_GetObjectItem(newccuItem,VALUERANGE_STRING);
                kk_creater_nodeid(node->deviceCode,channel,nodeid);
                cJSON_AddStringToObject(subdevicesItem, OPCODE_STRING, opcodemap);
                cJSON_AddStringToObject(subdevicesItem, NODEID_STRING, nodeid);
                sprintf(indxId,"%d",idx++);
                cJSON_AddStringToObject(subdevicesItem, "index", indxId);
                
                if(strcmp(dataType,"int") == 0){
                    int value  = cJSON_GetObjectItem(newccuItem,VALUE_STRING)->valueint;
                    if(range != NULL){
                        int index = kk_get_int_value_idx(range,value);
                        cJSON_AddStringToObject(subdevicesItem, "arg", kk_value_int_map_string(opcodemap,node,index));
                    }
                }
                cJSON_AddItemToArray(device_status, subdevicesItem);
                newccuItem = newccuItem->next;
            }
            
        }
        
    }
    #endif
    cJSON_AddItemToObject(root, DEVICE_STATUS_STRING, device_status);
    return 0;
}
int kk_map_dev_update_int_value(kk_map_dev_node_t *node,char *identifier,int val)
{
    int ret = 0;

    if(node != NULL && node->newccu != NULL){
        cJSON * newccuItem = node->newccu->child;
        while(newccuItem != NULL){
            char *identifier_tmp = cJSON_GetObjectItem(newccuItem,MSG_INDENTIFIER_STR)->valuestring;
            if(strcmp(identifier_tmp,identifier) == 0){
                cJSON_ReplaceItemInObject(newccuItem, "value", cJSON_CreateNumber(val));
                break;
            }
            newccuItem = newccuItem->next;
        }    
    }    
    return 0;
}
int kk_map_dev_update_int_value_by_devicecode(char *deviceCode,char *identifier,int val)
{
    int ret = 0;
    kk_map_dev_node_t *node = NULL;
    ret = kk_map_dev_search_by_deviceCode(deviceCode,&node);
    if(ret != 0){
        ERROR_PRINT("kk_map_dev_update_int_value, err: %s", deviceCode);
        return ret;
    }
    if(node != NULL && node->newccu != NULL){
        cJSON * newccuItem = node->newccu->child;
        while(newccuItem != NULL){
            char *identifier_tmp = cJSON_GetObjectItem(newccuItem,MSG_INDENTIFIER_STR)->valuestring;
            if(strcmp(identifier_tmp,identifier) == 0){
                cJSON_ReplaceItemInObject(newccuItem, "value", cJSON_CreateNumber(val));
                break;
            }
            newccuItem = newccuItem->next;
        }    
    }    
    return 0;
}

int kk_map_dev_search_by_deviceCode(char *deviceCode, kk_map_dev_node_t **node)
{
    kk_map_dev_ctx *ctx = _kk_map_dev_ctx();
    kk_map_dev_node_t *search_node = NULL;

    list_for_each_entry(search_node, &ctx->dev_list, linked_list, kk_map_dev_node_t) {
        if ( (strlen(search_node->deviceCode) == strlen(deviceCode)) &&
            (memcmp(search_node->deviceCode, deviceCode, strlen(deviceCode)) == 0)) {
            /* dm_log_debug("Device Found, devid: %d", devid); */
            if (node) {
                *node = search_node;
            }
            return 0;
        }
    }

    ERROR_PRINT("Device Not Found, deviceCode: %s", deviceCode);
    return -1;
}
kk_map_dev_node_t *kk_map_dev_add(char *deviceCode,char *productCode,char *gwdeviceCode)
{
    #if 1
    kk_map_dev_node_t *node = NULL;
    kk_map_dev_ctx *ctx = _kk_map_dev_ctx();

    node = malloc(sizeof(kk_map_dev_node_t));
    if (node == NULL) {
        return NULL;
    }    
printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    _kk_map_dev_mutex_lock();
    memset(node,0x0,sizeof(kk_map_dev_node_t));
    memcpy(node->gwDeviceCode,gwdeviceCode,strlen(gwdeviceCode));
    memcpy(node->deviceCode,deviceCode,strlen(deviceCode));
    memcpy(node->productCode,productCode,strlen(productCode));
    kk_open_cfg_file(productCode,node);
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    INIT_LIST_HEAD(&node->linked_list);
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    list_add_tail(&node->linked_list, &ctx->dev_list);  
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);  
    _kk_map_dev_mutex_unlock();
    printf("[%s][%d]\n",__FUNCTION__,__LINE__);
    return node;
    #endif
}