#include "kk_ccu_msg.h"

typedef cJSON *(*convert_func)(cJSON *,cJSON *);

typedef struct
{
	char *type;
	convert_func func;
}CONVERT_ITEM_S;

static cJSON *bool_type_convert(cJSON *n_id,cJSON *n_dataType);
static cJSON *int_type_convert(cJSON *n_id,cJSON *n_dataType);
static cJSON *double_type_convert(cJSON *n_id,cJSON *n_dataType);
static cJSON *string_bool_type_convert(cJSON *n_id,cJSON *n_dataType);
static cJSON *string_int_type_convert(cJSON *n_id,cJSON *n_dataType);
static cJSON *string_double_type_convert(cJSON *n_id,cJSON *n_dataType);
static cJSON *string_time_type_convert(cJSON *n_id,cJSON *n_dataType);
static cJSON *fit_type_convert(cJSON *n_id,cJSON *n_dataType);
static cJSON *string_type_convert(cJSON *n_id,cJSON *n_dataType);

static CONVERT_ITEM_S convert_table[] = {
	{"bool",bool_type_convert},
	{"int",int_type_convert},
	{"double",double_type_convert},
	{"string_bool",string_bool_type_convert},
	{"string_int",string_int_type_convert},
	{"string_double",string_double_type_convert},
	{"string_time",string_time_type_convert},
	{"fit",fit_type_convert},
	{"string",string_type_convert},	
};
static cJSON *string_type_convert(cJSON *n_id,cJSON *n_dataType)
{
	cJSON *args = NULL;
	char buf[16] = {0};
	if(n_id == NULL){
		return NULL;
	}
	if(n_id->type==cJSON_Number){
		sprintf(buf,"%d",n_id->valueint);
		args = cJSON_CreateString(buf);
	}
	return args;
}
static cJSON *bool_type_convert(cJSON *n_id,cJSON *n_dataType)
{
	cJSON *args = NULL;
	int bVal = 0;

	if(strcmp(n_dataType->valuestring,"dummy")==0) {
		return NULL;
	}

	if(n_id->type==cJSON_Number){
		if((strcmp(n_dataType->valuestring,"int")==0) ||
			(strcmp(n_dataType->valuestring,"bool")==0)||
			(strcmp(n_dataType->valuestring,"string_int")==0)||
			(strcmp(n_dataType->valuestring,"string_bool")==0)){
			args = cJSON_CreateBool(n_id->valueint);
		}else if(strcmp(n_dataType->valuestring,"double")==0||
			strcmp(n_dataType->valuestring,"string_double")==0) {
			bVal = (n_id->valuedouble>0) ? 1 : 0;
			args = cJSON_CreateBool(bVal);
		}
	}else if(n_id->type==cJSON_String){
		if((strcmp(n_dataType->valuestring,"int")==0) ||
			(strcmp(n_dataType->valuestring,"bool")==0)||
			(strcmp(n_dataType->valuestring,"string_int")==0)){
				args = cJSON_CreateBool(atoi(n_id->valuestring));
		}else if(strcmp(n_dataType->valuestring,"double")==0||
			strcmp(n_dataType->valuestring,"string_double")==0) {
			bVal = (atof(n_id->valuestring)>0) ? 1 : 0;
			args = cJSON_CreateBool(bVal);
		}else if(strcmp(n_dataType->valuestring,"string_bool")==0) {
			if(strcmp(n_id->valuestring,"true")==0 ||
				strcmp(n_id->valuestring,"TRUE")==0){
				args = cJSON_CreateBool(1);
			}else if(strcmp(n_id->valuestring,"true")==0 ||
				strcmp(n_id->valuestring,"TRUE")==0){
				args = cJSON_CreateBool(0);
			}
		}
	}else if(n_id->type==cJSON_False){
		args = cJSON_CreateNumber(0);
	}else if(n_id->type==cJSON_True){
		args = cJSON_CreateNumber(1);
	}
	
	return args;
}

static cJSON *int_type_convert(cJSON *n_id,cJSON *n_dataType)
{
	cJSON *args = NULL;
	
	if(strcmp(n_dataType->valuestring,"dummy")==0) {
		return NULL;
	}

	if(n_id->type==cJSON_Number){
		if((strcmp(n_dataType->valuestring,"int")==0) ||
			(strcmp(n_dataType->valuestring,"bool")==0)||
			(strcmp(n_dataType->valuestring,"string_int")==0)){
			args = cJSON_CreateNumber(n_id->valueint);
		}else if(strcmp(n_dataType->valuestring,"double")==0||
			(strcmp(n_dataType->valuestring,"string_double")==0)) {
			args = cJSON_CreateNumber(n_id->valuedouble);
		}else if(strcmp(n_dataType->valuestring,"string_bool")==0) {
			if(strcmp(n_id->valuestring,"true")==0 ||
				strcmp(n_id->valuestring,"TRUE")==0){
				args = cJSON_CreateNumber(1);
			}else if(strcmp(n_id->valuestring,"true")==0 ||
				strcmp(n_id->valuestring,"TRUE")==0){
				args = cJSON_CreateNumber(0);
			}
		}
	}else if(n_id->type==cJSON_String){
		if((strcmp(n_dataType->valuestring,"int")==0) ||
			(strcmp(n_dataType->valuestring,"bool")==0)||
			(strcmp(n_dataType->valuestring,"string_int")==0)){
			args = cJSON_CreateNumber(atoi(n_id->valuestring));
		}else if(strcmp(n_dataType->valuestring,"double")==0||
			strcmp(n_dataType->valuestring,"string_double")==0) {
			args = cJSON_CreateNumber(atof(n_id->valuestring));
		}else if(strcmp(n_dataType->valuestring,"string_bool")==0) {
			if(strcmp(n_id->valuestring,"true")==0 ||
				strcmp(n_id->valuestring,"TRUE")==0){
				args = cJSON_CreateNumber(1);
			}else if(strcmp(n_id->valuestring,"true")==0 ||
				strcmp(n_id->valuestring,"TRUE")==0){
				args = cJSON_CreateNumber(0);
			}
		}
	}else if(n_id->type==cJSON_False){
		args = cJSON_CreateNumber(0);
	}else if(n_id->type==cJSON_True){
		args = cJSON_CreateNumber(1);
	}

	return args;
}

static cJSON *double_type_convert(cJSON *n_id,cJSON *n_dataType)
{
	return int_type_convert(n_id,n_dataType);
}

static cJSON *string_bool_type_convert(cJSON *n_id,cJSON *n_dataType)
{
	cJSON *args = NULL;
	int flag = -1;

	if(strcmp(n_dataType->valuestring,"dummy")==0) {
		return NULL;
	}
	if(n_id->type == cJSON_True) {
		flag==1;
	}else if(n_id->type == cJSON_False){
		flag==0;
	}else if(n_id->type == cJSON_Number){
		if((strcmp(n_dataType->valuestring,"int")==0) ||
			(strcmp(n_dataType->valuestring,"bool")==0)||
			(strcmp(n_dataType->valuestring,"string_int")==0)||
			(strcmp(n_dataType->valuestring,"string_bool")==0)){
			flag = (n_id->valueint>0) ? 1 : 0;
		}else if(strcmp(n_dataType->valuestring,"double")==0||
			strcmp(n_dataType->valuestring,"string_double")==0) {
			flag = (n_id->valuedouble>0) ? 1 : 0;
		}
	}else if(n_id->type == cJSON_String){
		if((strcmp(n_dataType->valuestring,"int")==0) ||
			(strcmp(n_dataType->valuestring,"bool")==0)||
			(strcmp(n_dataType->valuestring,"string_int")==0)){
			flag = (atoi(n_id->valuestring)>0) ? 1 : 0;
		}else if(strcmp(n_dataType->valuestring,"double")==0||
			strcmp(n_dataType->valuestring,"string_double")==0) {
			flag = (atof(n_id->valuestring)>0) ? 1 : 0;
		}else if(strcmp(n_dataType->valuestring,"string_bool")==0) {
			if(strcmp(n_id->valuestring,"true")==0 ||
				strcmp(n_id->valuestring,"TRUE")==0){
				flag = 1;
			}else if(strcmp(n_id->valuestring,"false")==0 ||
				strcmp(n_id->valuestring,"FALSE")==0){
				flag = 0;
			}
		}
	}

	if(flag==1) {
		args = cJSON_CreateString("true");
	}else if(flag==0){
		args = cJSON_CreateString("false");
	}
	
	return args;
}

static cJSON *string_val_type_convert(int type,cJSON *n_id,cJSON *n_dataType)
{
	cJSON *args = NULL;
	char sVal[32] = {0};
	union {
		int iVal;
		double dVal;
	}val = {0};
	memset(sVal,0,sizeof(sVal));

	if(strcmp(n_dataType->valuestring,"dummy")==0) {
		return NULL;
	}

	if(n_id->type == cJSON_True) {
		args = cJSON_CreateTrue();
	}else if(n_id->type == cJSON_False){
		args = cJSON_CreateFalse();
	}else if(n_id->type==cJSON_Number){
		if((strcmp(n_dataType->valuestring,"int")==0) ||
			(strcmp(n_dataType->valuestring,"bool")==0)){
			if(type==1){
				val.dVal = (n_id->valueint>0) ? 1 : 0;
			}else{
				//printf("n_id->valueint----------------->:%d\n",n_id->valueint);
				val.iVal = (n_id->valueint>0) ? n_id->valueint : 0;
			}
		}else if(strcmp(n_dataType->valuestring,"double")==0) {
			if(type==1){
				val.dVal = n_id->valuedouble;
			}else{
				val.iVal = n_id->valueint;
			}
		}
	}else if(n_id->type==cJSON_String){
		if(strcmp(n_dataType->valuestring,"string_int")==0){
			if(type==1){
				val.dVal = atoi(n_id->valuestring);
			}else{
				val.iVal = atoi(n_id->valuestring);
			}
		}else if(strcmp(n_dataType->valuestring,"string_double")==0){
			if(type==1){
				val.dVal = atof(n_id->valuestring);
			}else{
				val.iVal = atof(n_id->valuestring);
			}
		}
	}else if(n_id->type==cJSON_False||n_id->type==cJSON_True){
		if(strcmp(n_dataType->valuestring,"string_bool")==0){

			if(strcmp(n_id->valuestring,"true")==0 ||
				strcmp(n_id->valuestring,"TRUE")==0){
				if(type==1){
					val.dVal = 1;
				}else{
					val.iVal = 1;
				}
			}else if(strcmp(n_id->valuestring,"false")==0 ||
				strcmp(n_id->valuestring,"FALSE")==0){
				if(type==1){
					val.dVal = 0;
				}else{
					val.iVal = 0;
				}
			}
		}
	}

	
	if(type==1){
		snprintf(sVal,sizeof(sVal),"%f",val.dVal);
	}else{
		snprintf(sVal,sizeof(sVal),"%d",val.iVal);
	}

	args = cJSON_CreateString(sVal);

	return args;
}

cJSON *string_int_type_convert(cJSON *n_id,cJSON *n_dataType)
{
	return string_val_type_convert(0,n_id,n_dataType);
}
cJSON *string_double_type_convert(cJSON *n_id,cJSON *n_dataType)
{
	return string_val_type_convert(1,n_id,n_dataType);
}

cJSON *string_time_type_convert(cJSON *n_id,cJSON *n_dataType)
{
	cJSON *args = NULL;
	int val;
	char tm[10] = {0};

	if(strcmp(n_dataType->valuestring,"dummy")==0) {
		return NULL;
	}


	if(strcmp(n_dataType->valuestring,"double")==0){
		val = n_id->valuedouble * 10;

		memset(tm,0,sizeof(tm));
		snprintf(tm,sizeof(tm),"%02d:%2s",(int)n_id->valuedouble,((val%10>=5)?"30":"00"));
		args = cJSON_CreateString(tm);
	}

	
	return args;
}

cJSON *fit_type_convert(cJSON *n_id,cJSON *n_dataType)
{
	cJSON *args = NULL;

	if(n_id->type == cJSON_True) {
		args = cJSON_CreateTrue();
	}else if(n_id->type == cJSON_False){
		args = cJSON_CreateFalse();
	}else if(n_id->type == cJSON_NULL){
		args = cJSON_CreateNull();
	}else if(n_id->type == cJSON_Number){
		args = cJSON_CreateNumber(n_id->valuedouble);
	}else if(n_id->type == cJSON_String){
		args = cJSON_CreateString(n_id->valuestring);
	}
	
	return args;
}

cJSON * msg_convert_value(cJSON *d_type,cJSON *s_type,cJSON *value)
{
	int i,size;
	char *pVal = NULL;
	cJSON *rlt = NULL;
	CONVERT_ITEM_S *crt;


	if(d_type==NULL||s_type==NULL||value==NULL||
		d_type->type!=cJSON_String||s_type->type!=cJSON_String){
		debug_log(LOG_DEBUG_LEVEL,"[ERR] para.\n");
		return NULL;
	}


	pVal = cJSON_Print(value);
	debug_log(LOG_DEBUG_LEVEL,"[convert]type:%s->%s,val=%s.\n",s_type->valuestring,d_type->valuestring,pVal);
	free(pVal);
	
	

	size = sizeof(convert_table)/sizeof(CONVERT_ITEM_S);
	crt = &convert_table[0];
	
	for(i=0;i<size;i++,crt++){
		if(strcmp(d_type->valuestring,crt->type)==0) {
			if(crt->func){
				rlt = crt->func(value,s_type);
			}
			break;
		}
	}
	return rlt;
}

cJSON *map_type_convert(cJSON *s_dataType,cJSON *s_valueRange,cJSON *value,cJSON *d_valueRange)
{
	cJSON *args = NULL;
	cJSON *rlt;
	char *sVrg = NULL,*dVrg = NULL,*pVal = NULL;
	int j;
	int vra_size;

	
	if(s_valueRange==NULL||s_valueRange->type!=cJSON_Array||
		d_valueRange==NULL||d_valueRange->type!=cJSON_Array){
		debug_log(LOG_DEBUG_LEVEL,"[ERR] range.\n");
		return NULL;
	}
	if(s_dataType==NULL||s_dataType->type!=cJSON_String){
		debug_log(LOG_DEBUG_LEVEL,"[ERR] dataType.\n");
		return NULL;
	}
	
	sVrg = cJSON_Print(s_valueRange);
	dVrg = cJSON_Print(d_valueRange);
	pVal = cJSON_Print(value);
	debug_log(LOG_DEBUG_LEVEL,"[convert] s_dataType:%s,val=%s\n",s_dataType->valuestring,pVal);
	debug_log(LOG_INFO_LEVEL,"s_valueRange=%s\n",sVrg);
	debug_log(LOG_INFO_LEVEL,"d_valueRange=%s\n",dVrg);
	free(sVrg);
	free(dVrg);
	free(pVal);

	vra_size = cJSON_GetArraySize(s_valueRange);
	for(j=0;j<vra_size;j++){
		if(strcmp(s_dataType->valuestring,"dummy")==0){
			continue ;
		}
		rlt = cJSON_GetArrayItem(s_valueRange,j);
	
		if(strcmp(s_dataType->valuestring,"bool")==0 ||
			strcmp(s_dataType->valuestring,"int")==0) {
			if(rlt->valueint == value->valueint) {
				args = cJSON_GetArrayItem(d_valueRange,j);
				printf("222:%s\n",cJSON_Print(args));
				break ;
			}
		}else if(strcmp(s_dataType->valuestring,"double")==0){
			if(rlt->valuedouble == value->valuedouble) {
				args = cJSON_GetArrayItem(d_valueRange,j);
				break ;
			}
		}else if(strstr(s_dataType->valuestring,"string")){
			if(strcmp(rlt->valuestring,value->valuestring)==0){
				args = cJSON_GetArrayItem(d_valueRange,j);
				break ;
			}
		}else if(strstr(s_dataType->valuestring,"map")){
			
			if(rlt->type==cJSON_String){
				
				if(strcmp(rlt->valuestring,value->valuestring)==0){
				
					args = cJSON_GetArrayItem(d_valueRange,j);
					break ;
				}
			}else if(rlt->type==cJSON_Number){
			
				if(rlt->valueint == value->valueint) {
			
					args = cJSON_GetArrayItem(d_valueRange,j);
					break ;
				}
			}
			
		}
	}
	return args;
}








cJSON *ccu_value_convert(cJSON *s_dType,cJSON *s_range,cJSON *d_dType,cJSON *d_range,cJSON *value)
{
	cJSON *val = NULL;


	if(strcmp(d_dType->valuestring,"map")==0){
		printf("[%s][%d]\n",__FUNCTION__,__LINE__);


		val = map_type_convert(s_dType,s_range,value,d_range);
	}else{
		printf("[%s][%d]\n",__FUNCTION__,__LINE__);
		val = msg_convert_value(d_dType,s_dType,value);
	}

	return val;
}


int kk_lan_get_msg_id(void)
{
	static int id;
	return ++id;
}

int kk_lan_get_msg_id_str(char *msgId,int size)
{
	memset(msgId,0,size);
	snprintf(msgId,size,"%d",kk_lan_get_msg_id());
	return 0;
}










int kk_lan_add_val_to_obj(cJSON *obj,cJSON *val,const char *id)
{
	if(id==NULL||obj==NULL||obj->type!=cJSON_Object||val==NULL){
		debug_log(LOG_DEBUG_LEVEL,"[err] para.\n");
		return -1;
	}
	
	debug_log(LOG_DEBUG_LEVEL,"[add] id(%s),type(%d).\n",id,val->type);

	if(val->type==cJSON_False){
		cJSON_AddFalseToObject(obj,id);
	}else if(val->type==cJSON_True){
		cJSON_AddTrueToObject(obj,id);
	}else if(val->type==cJSON_NULL){
		cJSON_AddNullToObject(obj,id);
	}else if(val->type==cJSON_Number){
		cJSON_AddNumberToObject(obj,id,val->valuedouble);
	}else if(val->type==cJSON_String){
		cJSON_AddStringToObject(obj,id,val->valuestring);
	}else{
		debug_log(LOG_DEBUG_LEVEL,"[err] nonsupport type(%d).\n",val->type);
		return -1;
	}
	return 0;
}


int kk_lan_replace_val_to_obj(cJSON *obj,cJSON *val,const char *id)
{
	char *pVal = NULL;
	if(id==NULL||obj==NULL||obj->type!=cJSON_Object||val==NULL){
		debug_log(LOG_DEBUG_LEVEL,"[err] para.\n");
		return -1;
	}

	pVal = cJSON_Print(val);
	debug_log(LOG_DEBUG_LEVEL,"[replace] id=%s,type=%d,val=%s.\n",id,val->type,pVal);
	free(pVal);
	
	if(val->type==cJSON_False){
		cJSON_ReplaceItemInObject(obj, id, cJSON_CreateFalse());
	}else if(val->type==cJSON_True){
		cJSON_ReplaceItemInObject(obj, id, cJSON_CreateTrue());
	}else if(val->type==cJSON_NULL){
		cJSON_ReplaceItemInObject(obj, id, cJSON_CreateNull());
	}else if(val->type==cJSON_Number){
		cJSON_ReplaceItemInObject(obj, id, cJSON_CreateNumber(val->valuedouble));
	}else if(val->type==cJSON_String){
		cJSON_ReplaceItemInObject(obj, id, cJSON_CreateString(val->valuestring));
	}else{
		debug_log(LOG_DEBUG_LEVEL,"[err] nonsupport type(%d).\n",val->type);
		return -1;
	}
	return 0;
}









