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

#include "kk_log.h"

#include "klist.h"
#include "kk_product.h"
#include "com_api.h"
#include "kk_opcode.h"
#include "kk_lan_ctrl.h"
#include "kk_data_mng.h"

#include "kk_oldccu_msg.h"



cJSON *old_ccu_msg_build_json_node_int(int nodeid,const char*  opcode,const char*  status,cJSON * arg)
{
	cJSON *root;

	if(nodeid==NULL||opcode==NULL||arg==NULL) {
		return NULL;
	}
	
	root=cJSON_CreateObject();
	if(root){
		cJSON_AddNumberToObject(root, "nodeid", nodeid);
		cJSON_AddStringToObject(root, "opcode", opcode);
		cJSON_AddStringToObject(root, "status", "success");
		cJSON_AddItemToObject(root, "arg", arg);
	}
	return root;
}


cJSON *old_ccu_msg_build_json(const char* nodeid,const char*  opcode,const char*  status,cJSON * arg)
{
	cJSON *root;

	if(nodeid==NULL||opcode==NULL||arg==NULL) {
		return NULL;
	}
	
	root=cJSON_CreateObject();
	if(root){
		cJSON_AddStringToObject(root, "nodeid", nodeid);
		cJSON_AddStringToObject(root, "opcode", opcode);
		cJSON_AddStringToObject(root, "status", "success");
		cJSON_AddItemToObject(root, "arg", arg);
	}
	return root;
}

cJSON *old_ccu_msg_build(const char* nodeid,const char* opcode,const char* status,const char* arg)
{
	cJSON *root;

	if(nodeid==NULL||opcode==NULL||arg==NULL) {
		return NULL;
	}
	
	root=cJSON_CreateObject();
	if(root){
		cJSON_AddStringToObject(root, "nodeid", nodeid);
		cJSON_AddStringToObject(root, "opcode", opcode);
		if(status==NULL){
			cJSON_AddStringToObject(root, "status", "success");
		}else{
			cJSON_AddStringToObject(root, "status", status);
		}
		cJSON_AddStringToObject(root, "arg", arg);
	}
	return root;
}

int send_msg_to_module(cJSON *root)
{
	char *msg;
	
	if(root==NULL){
		return -1;
	}

	if((msg = cJSON_Print(root))!=NULL){
		printf("[lan->module]json:\n%s\n",msg);
		cJSON_Minify(msg);
		kk_send_data_to_sdk(msg);
		free(msg);
	}

	return 0;
}








cJSON * val_conver_new2old(cJSON *newccuItem,cJSON *oldccuItem,int syn_type)
{
	cJSON *n_dataType = cJSON_GetObjectItem(newccuItem,DATATYPE_STRING);
	cJSON * n_value  = cJSON_GetObjectItem(newccuItem,"value");

	cJSON *o_dataType;

	cJSON *o_valueRange = cJSON_GetObjectItem(oldccuItem,"valueRange");
	cJSON *n_valueRange = cJSON_GetObjectItem(newccuItem,"valueRange");

	if(syn_type==1){
		o_dataType = cJSON_GetObjectItem(oldccuItem,"synType");
	}else{
		o_dataType = cJSON_GetObjectItem(oldccuItem,DATATYPE_STRING);
	}
	return ccu_value_convert(n_dataType,n_valueRange,o_dataType,o_valueRange,n_value);
}











cJSON *kk_devicestatus_build(kk_map_dev_node_t *node)
{
	int i,num = 0;
	char nodeid[32] = {0};

	
	cJSON *newccu,*oldccu;
	cJSON *dev_status;
	

	printf("@@@@kk_devicestatus_build\n");
	if (node == NULL ||node->syn_opcode==NULL){
		return NULL;
	}

	newccu = node->newccu;
	oldccu = node->oldccu;

	if(newccu==NULL||newccu->type!=cJSON_Object ||
		oldccu==NULL||oldccu->type!=cJSON_Object){
		return NULL;
	}

	dev_status = cJSON_CreateObject();

	num = cJSON_GetArraySize(newccu);
	for(i=0;i<num;i++){
		cJSON * newccuItem = cJSON_GetArrayItem(newccu,i);
		cJSON * oldccuItem = cJSON_GetArrayItem(oldccu,i);
		cJSON *synType = cJSON_GetObjectItem(oldccuItem,"synType");
		cJSON *synKey = cJSON_GetObjectItem(oldccuItem,"syn");
		cJSON *val = NULL;
		cJSON *status = NULL;
		char indexId[4] = {0};
		
		if(synType){
			if(synType->type!=cJSON_String ||synKey==NULL ||synKey->type!=cJSON_String) {
				continue ;
			}

			status = cJSON_CreateObject();
			
			kk_creater_nodeid(node->deviceCode,1,nodeid,atoi(node->opearteType));

			cJSON_AddStringToObject(status, OPCODE_STRING, node->syn_opcode);
			cJSON_AddNumberToObject(status, NODEID_STRING, atoi(nodeid));

			memset(indexId,0,sizeof(indexId));
			snprintf(indexId,sizeof(indexId),"%d",i+1);
			
			cJSON_AddStringToObject(status, "index", indexId);

			//todo:
			if(strcmp(synType->valuestring,"timing_shutdown")==0) {
				cJSON *syn_obj = cJSON_CreateObject();

				double t=cJSON_GetObjectItem(newccuItem,"value")->valuedouble;
				char buff[32]={0};

				snprintf(buff,32,"%f",t);
					
				if(t>0){
					cJSON_AddBoolToObject(syn_obj, "enable",1);
					cJSON_AddStringToObject(syn_obj, "time",buff);
				}else{
					cJSON_AddBoolToObject(syn_obj, "enable",0);
					cJSON_AddNullToObject(syn_obj, "time");
				}

				cJSON_AddItemToObject(dev_status, synKey->valuestring,syn_obj);
				
			}else{
				if((val = val_conver_new2old(newccuItem,oldccuItem,1))!=NULL){
					add_val_to_obj(dev_status,val,synKey->valuestring);
				}
			}
		}
	}

	printf("@##$%^&&*(*(((*^%$$#@@@--->%s\n",cJSON_Print(dev_status));

	return dev_status;
}







static int update_device_status(int nodeId,const char *opcode,const char *arg)
{
	cJSON *msg;
	char *nodeStr;

	if(arg==NULL){
		return -1;
	}
	printf("[%s][%d]nodeId=%d,status=%s\n",__FUNCTION__,__LINE__,nodeId,arg);

	if((nodeStr=node_string(nodeId))!=NULL){
		msg = old_ccu_msg_build(nodeStr,opcode,"success",arg);
		send_msg_to_module(msg);
		cJSON_Delete(msg);
		free(nodeStr);
		return 0;
	}

	return -1;
}



cJSON * attr_report_conver(const char *deviceCode,kk_map_dev_node_t *devNode,cJSON *params)
{
	cJSON *root;
	//
	cJSON *newccu;
	cJSON *n_item;
	cJSON *n_id,*n_valueRange,*n_dataType;
	cJSON *n_value;


	//
	cJSON *oldccu;
	cJSON *o_item;
	cJSON *o_id_map,*o_valueRange,*o_dataType;
	cJSON *o_value;


	cJSON *val;
	cJSON *item_size;
	cJSON *channel;
	cJSON *epNum=NULL;
	cJSON *opcode;
	

	int i,j;
	int ch;
	int nodeId;
	char *node_str;
	cJSON *msg;
	cJSON *args;

	
	oldccu = devNode->oldccu;
	newccu = devNode->newccu;

	item_size = cJSON_GetArraySize(oldccu);
	printf("[%s][%d]\n",__FUNCTION__,__LINE__);

	for(i=0;i<item_size;i++){
		o_item = cJSON_GetArrayItem(oldccu,i);
		n_item = cJSON_GetArrayItem(newccu,i);
	
		o_id_map = cJSON_GetObjectItem(o_item,"identifiermap");


		n_id = cJSON_GetObjectItem(params,o_id_map->valuestring);
		printf("[%s][%d]\n",__FUNCTION__,__LINE__);
		if(n_id!=NULL){
			
			n_dataType = cJSON_GetObjectItem(n_item,"dataType");
			n_valueRange = cJSON_GetObjectItem(n_item,"valueRange");
		
			o_dataType = cJSON_GetObjectItem(o_item,"dataType");
			o_valueRange = cJSON_GetObjectItem(o_item,"valueRange");


			channel = cJSON_GetObjectItem(o_item,"channel");
			epNum = cJSON_GetObjectItem(params,"epNum");
			if(channel==NULL||epNum==NULL){
				printf("[%s][%d]\n",__FUNCTION__,__LINE__);
				continue;
			}
			if(strlen(channel->valuestring)!=strlen(epNum->valuestring) ||
				strcmp(channel->valuestring,epNum->valuestring)!=0){
				printf("[%s][%d]\n",__FUNCTION__,__LINE__);
				continue;
			}

			ch = atoi(channel->valuestring);
			nodeId = kk_lan_db_node_get(deviceCode,ch);
			printf("[%s][%d]\n",__FUNCTION__,__LINE__);
			opcode =cJSON_GetObjectItem(o_item,"opcode");
			printf("[%s][%d]\n",__FUNCTION__,__LINE__);
			
			printf("[%s][%d]n_dataType->valuestring=%s,opcode->valuestring=%s\n",__FUNCTION__,__LINE__,n_dataType->valuestring,opcode->valuestring);

			//cJSON_ReplaceItemInObject(n_item, "value", cJSON_CreateString(""));//
			if(n_id->type==cJSON_False){
				printf("[replace] cJSON_False\n");
				cJSON_ReplaceItemInObject(n_item, "value", cJSON_CreateFalse());
			}else if(n_id->type==cJSON_True){
				printf("[replace] cJSON_True\n");
				cJSON_ReplaceItemInObject(n_item, "value", cJSON_CreateTrue());
			}else if(n_id->type==cJSON_NULL){
				printf("[replace] cJSON_NULL\n");
				cJSON_ReplaceItemInObject(n_item, "value", cJSON_CreateNull());
			}else if(n_id->type==cJSON_Number){
				printf("[replace] cJSON_Number\n");
				if(strcmp(n_dataType->valuestring,"double")==0){
					cJSON_ReplaceItemInObject(n_item, "value", cJSON_CreateNumber(n_id->valuedouble));
				}else {
					cJSON_ReplaceItemInObject(n_item, "value", cJSON_CreateNumber(n_id->valueint));
				}
			}else if(n_id->type==cJSON_String){
				printf("[replace] cJSON_String\n");
				cJSON_ReplaceItemInObject(n_item, "value", cJSON_CreateString(n_id->valuestring));
			}else if(n_id->type==cJSON_Array){
				printf("......................\n");
			}

			if((args = ccu_value_convert(n_dataType,n_valueRange,o_dataType,o_valueRange,n_id))!=NULL){
				update_device_status(nodeId,opcode->valuestring,args->valuestring);
				//cJSON_Delete(args);
			}

		}
	}

	if(devNode->syn_type==1){
		cJSON *arg;
		char *node_str;

		//arg = kk_devicestatus_build(devNode);
		arg =_kk_sync_devicestatus_arg_build(devNode);
		nodeId = kk_lan_db_node_get(deviceCode,1);

		node_str=node_string(nodeId);

		msg=old_ccu_msg_build_json(node_str,devNode->syn_opcode,NULL,arg);

		send_msg_to_module(msg);
		free(node_str);
		cJSON_Delete(msg);
	}	
	return root;
}





int del_device(const char *deviceCode,const char *nodeid)
{
	cJSON *msg;
	cJSON *arg;

	kk_map_dev_node_t *dev;

	if(deviceCode==NULL||nodeid==NULL){
		return -1;
	}

	arg = cJSON_CreateObject();
	cJSON_AddStringToObject(arg,"mac",deviceCode);
	msg = old_ccu_msg_build_json(nodeid,"DEL_DEVICE",NULL,arg);
	send_msg_to_module(msg);
	cJSON_Delete(msg);

	return 0;
}

int del_device_all_node(const char *deviceCode)
{
	#define MAX_CHANNEL_NUM 				32
	int list[MAX_CHANNEL_NUM] = {0};
	int i,num = 0;
	char *nodeid;
	
	//删除数据库
	kk_lan_db_node_delete(deviceCode);
	
	num = kk_lan_db_node_get_all(deviceCode,list);
	for(i=0;i<num;i++){
		nodeid = node_string(list[i]);
		del_device(deviceCode,nodeid);
		free(nodeid);
	}
	if(num){
		kk_handle_sync_info();
	}
}



void device_delete_sync(cJSON *payload)
{
	cJSON *params;
	cJSON *deviceCode;

	printf("[%s][%d]\n",__FUNCTION__,__LINE__);
	
	params = cJSON_GetObjectItem(payload,"params");
	
	deviceCode = cJSON_GetObjectItem(params, "deviceCode");
	del_device_all_node(deviceCode->valuestring);
	


}
void device_add_sync(cJSON *payload)
{

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








void device_new_device_sync(cJSON *payload)
{

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


void property_post_deal(const char *deviceCode,cJSON *payload)
{
	cJSON *params;

	kk_map_dev_node_t *dev;
	printf("[%s][%d]\n",__FUNCTION__,__LINE__);

	if(kk_map_dev_search_by_deviceCode(deviceCode, &dev)==0){
		
		params = cJSON_GetObjectItem(payload,"params");
		attr_report_conver(deviceCode,dev,params);
	}
}

void property_syn_deal(const char *deviceCode,cJSON *properties)
{
	cJSON *params;

	kk_map_dev_node_t *dev;

	if(kk_map_dev_search_by_deviceCode(deviceCode, &dev)==0){
		printf("[%s][%d]\n",__FUNCTION__,__LINE__);
		attr_report_conver(deviceCode,dev,properties);
	}
}


//同步信息
//房间同步


//布防撤防




/*
"0": "离家布防",
"1": "撤防",
"2": "在家布防",
"3": "区域布防"
*/
int arming_status_notify(int type)
{
	cJSON *msg = NULL;
	printf("[arming status notify] type=%d\n",type);
	if(type==0){
		msg = old_ccu_msg_build(WILDCARD_CHARACTER_STR,GUARD_STATUS_ARMING_LEAVE_HOME,SUCCESS_STR,WILDCARD_CHARACTER_STR);
	}else if(type==1){
		msg = old_ccu_msg_build(WILDCARD_CHARACTER_STR,GUARD_STATUS_DISARMING,SUCCESS_STR,WILDCARD_CHARACTER_STR);
	}else if(type==2){
		msg = old_ccu_msg_build(WILDCARD_CHARACTER_STR,GUARD_STATUS_ARMING_IN_HOME,SUCCESS_STR,WILDCARD_CHARACTER_STR);
	}else if(type==3){
		msg = old_ccu_msg_build(WILDCARD_CHARACTER_STR,ARMING_STATUS_GUARD_ZONE,SUCCESS_STR,WILDCARD_CHARACTER_STR);
	}else{
		printf("[unkown arming type]!!!\n");
		return -1;
	}
	
	
	send_msg_to_module(msg);
	cJSON_Delete(msg);
	return 0;
}










