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

#include "kk_data_mng.h"
#include "kk_login_handle.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(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){
		debug_log(LOG_INFO,"[lan->module]\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_value = NULL,*n_dataType = NULL,*o_dataType = NULL;
	cJSON *o_valueRange = NULL,*n_valueRange = NULL;

	if(newccuItem==NULL||newccuItem->type!=cJSON_Object||
		oldccuItem==NULL||oldccuItem->type!=cJSON_Object){
		debug_log(LOG_DEBUG,"[err] para.\n");
		return NULL;
	}

	o_valueRange = cJSON_GetObjectItem(oldccuItem,"valueRange");
	n_valueRange = cJSON_GetObjectItem(newccuItem,"valueRange");
	
	n_dataType = cJSON_GetObjectItem(newccuItem,DATATYPE_STRING);
	n_value  = cJSON_GetObjectItem(newccuItem,"value");

	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);
}

//更新设备状态
static int _kk_lan_update_device_status(int nodeId,cJSON *opcode,cJSON *arg)
{
	cJSON *msg = NULL;
	char nodeBuff[33] = {0};

	if(opcode==NULL||opcode->type!=cJSON_String||
		arg==NULL||arg->type!=cJSON_String){
		debug_log(LOG_DEBUG,"[err] para.\n");
		return -1;
	}
		
	debug_log(LOG_FOCUS,"nodeId=%d,opcode=%s,arg=%s\n",nodeId,opcode->valuestring,arg->valuestring);

	memset(nodeBuff,0,sizeof(nodeBuff));
	snprintf(nodeBuff,32,"%d",nodeId);

	msg = old_ccu_msg_build(nodeBuff,opcode->valuestring,"success",arg->valuestring);
	send_msg_to_module(msg);
	cJSON_Delete(msg);

	return 0;
}


static int _kk_lan_check_channel(cJSON *channelObj,cJSON *epNumObj)
{
	int channel = -1;
	
	if(channelObj!=NULL && epNumObj!=NULL){
		if(epNumObj->type!=cJSON_String){
			debug_log(LOG_INFO,"[err] epNumObj.\n");
			return -1;
		}
		if(strlen(channelObj->valuestring)!=strlen(epNumObj->valuestring) ||
			strcmp(channelObj->valuestring,epNumObj->valuestring)!=0){
			//debug_log(LOG_INFO,"[err] not match.\n");
			return -1;
		}
		channel = atoi(channelObj->valuestring);
	}else{
		if(channelObj==NULL){
			if(epNumObj->type!=cJSON_String){
				debug_log(LOG_INFO,"[err] epNumObj.\n");
				return -1;
			}
			channel = atoi(epNumObj->valuestring);
		}else if(epNumObj==NULL){
			if(channelObj->type!=cJSON_String){
				debug_log(LOG_INFO,"[err] channelObj.\n");
				return -1;
			}
			channel = atoi(channelObj->valuestring);
		}else{
			channel = 1;
		}
	}
	
	return channel;
}


static int _kk_lan_sync_device_status(const char *deviceCode,kk_map_dev_node_t *devNode)
{
	cJSON *msg = NULL;
	cJSON *arg = NULL;
	
	int nodeId = -1;
	char nodeBuff[33] = {0};

	if(devNode==NULL||devNode->syn_type!=1||devNode->syn_opcode==NULL){
		return -1;
	}

	if((arg =_kk_sync_devicestatus_arg_build(devNode))==NULL){
		debug_log(LOG_DEBUG,"[err] arg.\n");
		return -1;
	}

	if((nodeId = kk_lan_db_node_get(deviceCode,1))==-1){
		debug_log(LOG_DEBUG,"[err] nodeId.\n");
		return -1;
	}
	debug_log(LOG_FOCUS,"[sync] device status.\n");

	memset(nodeBuff,0,sizeof(nodeBuff));
	snprintf(nodeBuff,sizeof(nodeBuff),"%d",nodeId);


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

	send_msg_to_module(msg);
	cJSON_Delete(msg);
	return 0;
}



//属性转换
static int kk_lan_property_convert(const char *deviceCode,kk_map_dev_node_t *devNode,cJSON *params)
{
	int i = 0,channel = -1,nodeId = -1;
	cJSON *args = NULL,*valObj = NULL;

	cJSON *newccu = NULL,*oldccu = NULL;
	cJSON *n_item = NULL,*o_item = NULL;
	cJSON *o_valueRange = NULL,*n_valueRange = NULL;
	cJSON *o_dataType = NULL,*n_dataType = NULL;

	cJSON *opcode = NULL,*channelObj = NULL,*epNumObj = NULL;
	
	cJSON *n_id = NULL;

	cJSON *item_size = NULL;
	

	cJSON *epsAry = NULL,*epAryItem = NULL,*epAryEpNumObj = NULL;
	int j,mFlag=0,epsArySize = 0;
	


	if(deviceCode==NULL||devNode==NULL||
		params==NULL||params->type!=cJSON_Object){
		debug_log(LOG_DEBUG,"[err] para.\n");
		return -1;
	}

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

	item_size = cJSON_GetArraySize(newccu);

	for(i=0;i<item_size;i++){
		n_item = cJSON_GetArrayItem(newccu,i);

		if((o_item = cJSON_GetArrayItem(oldccu,i))==NULL||
			o_item->type!=cJSON_Object){
			debug_log(LOG_INFO,"[err] para.\n");
			continue ;
		}

		if((n_id = cJSON_GetObjectItem(n_item,"identifier"))==NULL||
			n_id->type!=cJSON_String){
			debug_log(LOG_DEBUG,"[err] cfg file.\n");
			continue;
		}


		
		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");

		if(n_dataType==NULL||n_dataType->type!=cJSON_String||
			o_dataType==NULL||o_dataType->type!=cJSON_String){
			debug_log(LOG_DEBUG,"[err] dataType.\n");
			continue;
		}

		channelObj = cJSON_GetObjectItem(o_item,"channel");
		epNumObj = cJSON_GetObjectItem(params,"epNum");
		if((channel = _kk_lan_check_channel(channelObj,epNumObj))==-1){
			debug_log(LOG_DEBUG,"[channel] %d.\n",channel);
			continue;
		}

		if((epsAry = cJSON_GetObjectItem(params,"eps"))!=NULL&&epsAry->type==cJSON_Array){
			epsArySize = cJSON_GetArraySize(epsAry);
			for(j=0;j<epsArySize;j++){
				epAryItem = cJSON_GetArrayItem(epsAry,j);

				epAryEpNumObj = cJSON_GetObjectItem(epAryItem,"epNum");
				if(epAryEpNumObj==NULL||epAryEpNumObj->type!=cJSON_String ||channel!=atoi(epAryEpNumObj->valuestring)){
					debug_log(LOG_NORMAL,"[epsAry match] next.\n");
					continue ;
				}
	
				if((valObj=cJSON_GetObjectItem(epAryItem,n_id->valuestring))==NULL){
					debug_log(LOG_NORMAL,"[epsAry match] next.\n");
					continue ;
				}else{
					mFlag = 1;
					break;
				}
			}
			if(mFlag!=1){
				continue ;
			}
		}else{
			if((valObj=cJSON_GetObjectItem(params,n_id->valuestring))==NULL){
				debug_log(LOG_NORMAL,"[match] next.\n");
				continue ;
			}
		}
				

		if((nodeId = kk_lan_db_node_get(deviceCode,channel))==-1){
			debug_log(LOG_DEBUG,"[err] not find node.\n");
			continue;
		}

		if((opcode = cJSON_GetObjectItem(n_item,"opcodemap"))==NULL||
			opcode->type!=cJSON_String){
			debug_log(LOG_DEBUG,"[err] cfg file.\n");
			continue;
		}
		
		

		kk_lan_replace_val_to_obj(n_item,valObj,"value");
			

		if((args = ccu_value_convert(n_dataType,n_valueRange,o_dataType,o_valueRange,valObj))!=NULL){
			_kk_lan_update_device_status(nodeId,opcode,args);
			//todo :
			//cJSON_Delete(args);

		}

	}

	_kk_lan_sync_device_status(deviceCode,devNode);

	return 0;
}



static int attr_indoorAir_report(cJSON *params)
{
	int k = 0;
	if(params == NULL){
		return -1;
	}
	cJSON *epsAry = cJSON_GetObjectItem(params,"eps");
	if(epsAry == NULL){
		return -1;
	}
	int epsize = cJSON_GetArraySize(epsAry);
	for(k = 0; k < epsize; k++){
		char tmpIdx[4] = {0};
		cJSON *infoItem = cJSON_GetArrayItem(epsAry,k);
		if(infoItem == NULL) continue;
		kk_send_indoorAir_status(infoItem);
	}
	return 0;
}
//属性状态上报处理
int kk_lan_property_post_deal(const char *deviceCode,cJSON *payload)
{
	cJSON *params = NULL;
	kk_map_dev_node_t *dev = NULL;

	debug_log(LOG_FOCUS,"[property post] deviceCode(%s).\n",deviceCode);
		
	if(kk_map_dev_search_by_deviceCode(deviceCode, &dev)==0){
		params = cJSON_GetObjectItem(payload,"params");

		if(strcmp(dev->productCode,"3062") == 0){
			attr_indoorAir_report(params);
		}else{
			return kk_lan_property_convert(deviceCode,dev,params);
		}
	}else{
		debug_log(LOG_DEBUG,"[err] not find deviceCode(%s).\n",deviceCode);
		return -1;
	}
	return 0;
}

//属性状态同步处理
int kk_lan_property_syn_deal(const char *deviceCode,cJSON *properties)
{
	cJSON *params = NULL;
	kk_map_dev_node_t *dev = NULL;
	
	debug_log(LOG_FOCUS,"[property syn] deviceCode(%s).\n",deviceCode);

	if(kk_map_dev_search_by_deviceCode(deviceCode, &dev)==0){
		return kk_lan_property_convert(deviceCode,dev,properties);
	}else{
		debug_log(LOG_DEBUG,"[err] not find deviceCode(%s).\n",deviceCode);
		return -1;
	}
	return 0;
}

//添加场景通知
void kk_lan_add_scene_notify(const char* scene_id)
{
	debug_log(LOG_FOCUS,"[notify] add scene(%s).\n",scene_id);

	kk_handle_sync_info();
}

//删除场景通知
void kk_lan_delete_scene_notify(const char* scene_id)
{
	debug_log(LOG_FOCUS,"[notify] delete scene(%s).\n",scene_id);

	cJSON *msg = old_ccu_msg_build(scene_id,"DELETE_SCENE",SUCCESS_STR,WILDCARD_CHARACTER_STR);
	send_msg_to_module(msg);
	cJSON_Delete(msg);
	
	kk_handle_sync_info();
}

//布防撤防状态通知(0-离家布防、1-撤防、2-在家布防、3-区域布防) 
int kk_lan_arming_status_notify(int type)
{
	cJSON *msg = NULL;
	
	debug_log(LOG_FOCUS,"[notify] arming status(%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{
		debug_log(LOG_DEBUG,"[err] unknow type(%d).\n",type);
		return -1;
	}

	send_msg_to_module(msg);
	cJSON_Delete(msg);
	return 0;
}


static int _kk_lan_delete_node(const char *deviceCode,const char *nodeid)
{
	cJSON *msg;
	cJSON *arg;
	char mac[32] = {0};
	kk_map_dev_node_t *dev;

	if(deviceCode==NULL||nodeid==NULL){
		debug_log(LOG_DEBUG,"[err] params.\n");
		return -1;
	}

	debug_log(LOG_FOCUS,"[del dev node] id(%s).\n",nodeid);
	
	arg = cJSON_CreateObject();
	_deviceCode_switchto_mac(deviceCode,mac);
	cJSON_AddStringToObject(arg,"mac",mac);
	msg = old_ccu_msg_build_json(nodeid,"DEL_DEVICE",NULL,arg);
	send_msg_to_module(msg);
	cJSON_Delete(msg);

	return 0;
}

static int _kk_lan_delete_device(const char *deviceCode)
{
	#define MAX_CHANNEL_NUM 				32
	int list[MAX_CHANNEL_NUM] = {0};
	int i,num = 0;
	char nodeId[33] = {0};

	num = kk_lan_db_node_get_all(deviceCode,list);

	debug_log(LOG_FOCUS,"[del dev] deviceCode(%s)/node num(%d).\n",deviceCode,num);
	
	for(i=0;i<num;i++){
		memset(nodeId,0,sizeof(nodeId));
		snprintf(nodeId,sizeof(nodeId),"%d",list[i]);
		_kk_lan_delete_node(deviceCode,nodeId);
	}
	
	//删除数据库
	kk_lan_db_node_delete(deviceCode);
	
	if(num){
		kk_handle_sync_info();
	}	
	return 0;
}

int kk_lan_device_delete_notify(cJSON *payload)
{
	cJSON *params = NULL;
	cJSON *deviceCode = NULL;

	if((params = cJSON_GetObjectItem(payload,"params"))==NULL||
		params->type!=cJSON_Object){
		debug_log(LOG_DEBUG,"[err] params.\n");
		return -1;
	}

	if((deviceCode = cJSON_GetObjectItem(params, "deviceCode"))==NULL||
		params->type!=cJSON_String){
		debug_log(LOG_DEBUG,"[err] deviceCode.\n");
		return -1;
	}

	_kk_lan_delete_device(deviceCode->valuestring);
	return 0;
}

void device_add_sync(cJSON *payload)
{
	//NEW_DEVICES
	printf("[%s][%d]\n",__FUNCTION__,__LINE__);
	kk_handle_sync_info();
}

