
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "kk_data_mng.h"
#include "kk_lan_node_db.h"
#include "kk_oldccu_msg.h"
#include "kk_utils.h"


static kk_map_dev_ctx g_map_dev_mgr = {0};




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

void _kk_map_dev_mutex_lock(void)
{
	kk_map_dev_ctx *ctx = _kk_map_dev_ctx();
	if (ctx->mutex) {
		kk_MutexLock(ctx->mutex);
	}
}
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;
}


void kk_map_dev_deinit(void)
{
	kk_map_dev_ctx *ctx = _kk_map_dev_ctx();
	kk_map_dev_node_t *node = NULL;
	kk_map_dev_node_t *n = NULL;

	//printf("[%s][%d]\n",__FUNCTION__,__LINE__);

	_kk_map_dev_mutex_lock();
	list_for_each_entry_safe(node,n,&ctx->dev_list, linked_list, kk_map_dev_node_t) {

		if (node != NULL) {

			if(node->json){
				//printf("[delete cjson] node->json.\n");
				cJSON_Delete(node->json);
			}
			
			if(node->syn_opcode) {
				//printf("[free] node->syn_opcode.\n");
				free(node->syn_opcode);
			}
			//printf("[remove list] node->linked_list\n");
			dlist_del(&node->linked_list);
			memset(node,0,sizeof(kk_map_dev_node_t));
			
		}
	}
	_kk_map_dev_mutex_unlock();
}


static kk_map_dev_node_t *kk_map_dev_node_create(const char *deviceCode,const char *productCode,const char *gwdeviceCode,
		const char *onlineStatus,char *buf)
{
	kk_map_dev_node_t *node = NULL;
	cJSON *json = NULL;
	cJSON *newccu = NULL,*oldccu = NULL,*channel = NULL,*optype = NULL;
	cJSON *syn_type = NULL,*syn_opcode = NULL;

	printf("kk_map_dev_node_create\n");
	node = malloc(sizeof(kk_map_dev_node_t));
	if (node == NULL) {
		debug_log(LOG_ALERT_LEVEL,"[err].\n");
		return NULL;
	}
	memset(node,0x0,sizeof(kk_map_dev_node_t));



	json = cJSON_Parse(buf);
	if(json == NULL){
		free(buf);
		free(node);
		debug_log(LOG_ALERT_LEVEL,"[err].\n");
		return NULL;
	}
		

	node->json = json;
	optype = cJSON_GetObjectItem(json, OPEARTETYPE_STRING);
	channel = cJSON_GetObjectItem(json, CHANNEL_STRING);
	newccu = cJSON_GetObjectItem(json, NEWCCU_STRING);
	oldccu = cJSON_GetObjectItem(json, OLDCCU_STRING);
	syn_type = cJSON_GetObjectItem(json, "syn_type");
	syn_opcode = cJSON_GetObjectItem(json, "syn_opcode");

	if(optype == NULL || optype->type!=cJSON_String ||
		channel==NULL||channel->type!=cJSON_Number){
		debug_log(LOG_ALERT_LEVEL,"[err].\n");
		goto err;
	}

	if(newccu==NULL||newccu->type!=cJSON_Array||
		oldccu==NULL||oldccu->type!=cJSON_Array){
		debug_log(LOG_ALERT_LEVEL,"[err].\n");
		goto err;
	}
		
	if(syn_type!=NULL){
		if(syn_type->type==cJSON_Number){
			if(syn_opcode==NULL||syn_opcode->type!=cJSON_String){
				debug_log(LOG_ALERT_LEVEL,"[err].\n");
				goto err;
			}
		}else{
			debug_log(LOG_ALERT_LEVEL,"[err].\n");
			goto err;
		}
	}

	
	memcpy(node->gwDeviceCode,gwdeviceCode,strlen(gwdeviceCode));
	memcpy(node->deviceCode,deviceCode,strlen(deviceCode));
	memcpy(node->productCode,productCode,strlen(productCode));
	node->online_status = (strcmp(onlineStatus,"1")==0)?1:0;
	debug_log(LOG_ALERT_LEVEL,"[add node]node->deviceCode=%s,node->online_status=%d\n",node->deviceCode,node->online_status);

	memcpy(node->opearteType,optype->valuestring,strlen(optype->valuestring));
	node->channelNum = channel->valueint;
	node->newccu = newccu;
	node->oldccu = oldccu;

	if(syn_type){
		node->syn_type = syn_type->valueint;
		node->syn_opcode= (char *)malloc(strlen(syn_opcode->valuestring)+1);
		memset(node->syn_opcode,0,strlen(syn_opcode->valuestring)+1);
		memcpy(node->syn_opcode,syn_opcode->valuestring,strlen(syn_opcode->valuestring));
		

	}
	

	free(buf);
	
	return node;

err:
	free(buf);
	free(node);
	return NULL;

}
static kk_map_dev_node_t *kk_map_dev_node_create_ex(const char *deviceCode,const char *productCode,const char *gwdeviceCode,
		const char *onlineStatus)
{
	kk_map_dev_node_t *node = NULL;
	cJSON *json = NULL;
	cJSON *newccu = NULL,*oldccu = NULL,*channel = NULL,*optype = NULL;
	cJSON *syn_type = NULL,*syn_opcode = NULL;

	printf("kk_map_dev_node_create\n");
	node = malloc(sizeof(kk_map_dev_node_t));
	if (node == NULL) {
		return NULL;
	}
	memset(node,0x0,sizeof(kk_map_dev_node_t));
	node->json = NULL;
	memcpy(node->gwDeviceCode,gwdeviceCode,strlen(gwdeviceCode));
	memcpy(node->deviceCode,deviceCode,strlen(deviceCode));
	memcpy(node->productCode,productCode,strlen(productCode));
	node->online_status = (strcmp(onlineStatus,"1")==0)?1:0;
	node->channelNum = 0;
	node->newccu = NULL;
	node->oldccu = NULL;
	return node;
}


static char *kk_open_lan_cfg_file(const char *deviceCode)
{
	char path[128] = {0};
	unsigned int filesize;
	FILE *fp;
	char *buf = NULL;


	snprintf(path,sizeof(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 NULL;
	}

	fseek(fp, 0L, SEEK_END);
	filesize = ftell(fp);	
	buf = malloc(filesize+1);
	if(buf == NULL)
	{
		fclose(fp);
		return NULL;
	}

	memset(buf,0x0,filesize+1);
	fseek(fp, 0L, SEEK_SET);
	fread(buf, 1, filesize, fp);
	//printf("[read lan cfg]:%s\n",buf);
	
	fclose(fp);
	return buf;
}
//todo:
int kk_creater_nodeid(char *deviceCode,int channel,char *nodeId)
{
	static int next = 1;
	int node=-1;
	
	if(deviceCode == NULL || nodeId == NULL){

		return -1;
	}

	if(kk_check_lan_node_exist(deviceCode,channel)){

		printf("[%s][%d]\n",__FUNCTION__,__LINE__);
		node = kk_lan_db_node_get(deviceCode,channel);
	}else{

		while(kk_check_lan_node(next)){
			++next;
		}
		if(0==kk_lan_db_node_insert(deviceCode,channel,next)){
			node=next;
		}
	}

	sprintf(nodeId,"%d",node);

	INFO_PRINT("[node]deviceCode=%s,channel=%d,node=%d,nodeId=%s\n",deviceCode,channel,node,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 "";
	}
	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 "";
}
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;
}

int mac_switchto_deviceCode(char *mac,char * deviceCode)
{
	char mac_bak[33] = {0};
	int i, j;
	int len =  strlen(mac);
	if(len!=23)
		return -1;
	
	for(i=0; i < len; i++)  /*将串s拷贝至串t*/
		mac_bak[i]=mac[i];
	mac_bak[i]='\0';

	for(i=0,j=0; i < len; i++){
		if((i+1)%3==0&&i!=0){
			continue;
		}
		deviceCode[j++] =mac_bak[i];
	}
	deviceCode[j]='\0';  /*在串s结尾加结束标志*/
	return 0;
}
int _deviceCode_switchto_mac(const 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;
}
































char *double_value_string(double val)
{
	char *value = (char *)malloc(33);
	memset(value,0,33);
	
	snprintf(value,32,"%6f",val);
	return value;
}











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(const 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_safe

    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\n", deviceCode);
	return -1;
}
int kk_map_dev_search_by_productCode(char *productCode, 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_safe
    list_for_each_entry(search_node, &ctx->dev_list, linked_list, kk_map_dev_node_t) {
		if ( (strlen(search_node->productCode) == strlen(productCode)) &&
            (memcmp(search_node->productCode, productCode, strlen(productCode)) == 0)) {
            /* dm_log_debug("Device Found, devid: %d", devid); */
            if (node) {
                *node = search_node;
            }
			printf("[find]%s\n",search_node->productCode);
            return 0;
        }
    }
	ERROR_PRINT("Device Not Found, productCode: %s\n", productCode);
	return -1;
}


kk_map_dev_node_t *kk_map_dev_node_add(const char *deviceCode,const char *productCode,const char *gwdeviceCode,const char *onlineStatus)
{
	kk_map_dev_node_t *node = NULL;
	kk_map_dev_ctx *ctx = _kk_map_dev_ctx();
	char *buf = NULL;


	if(deviceCode==NULL||productCode==NULL||
		gwdeviceCode==NULL||onlineStatus==NULL){
		return NULL;
	}

		
	_kk_map_dev_mutex_lock();
	if((buf = kk_open_lan_cfg_file(productCode))!=NULL){
		node = kk_map_dev_node_create(deviceCode,productCode,gwdeviceCode,onlineStatus,buf);
		
	}else{
		node = kk_map_dev_node_create_ex(deviceCode,productCode,gwdeviceCode,onlineStatus);	
	}
	if(node){
		INIT_LIST_HEAD(&node->linked_list);
		list_add_tail(&node->linked_list, &ctx->dev_list);
	}
	_kk_map_dev_mutex_unlock();

	return node;

}




























