#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 "cJSON.h"
#include "kk_ccu_msg.h"
#include "kk_oldccu_msg.h"
#include "kk_newccu_msg.h"
#include "kk_lan_node_db.h"
#include "kk_findccu_handle.h"
extern int kk_lan_get_ccuid(_OU_ char *device_code);


int match_opcode_pos(cJSON *array,const char *opcode,int ch)
{
	int i = 0;
	int pos = -1;
	cJSON *item;
	cJSON *mh;
	cJSON *channel;
	
	int size = cJSON_GetArraySize(array);
	for(;i<size;i++){
		item = cJSON_GetArrayItem(array,i);
		mh = cJSON_GetObjectItem(item,"opcode");
		channel = cJSON_GetObjectItem(item,"channel");
		if((strcmp(mh->valuestring,opcode)==0) &&
			(atoi(channel->valuestring)==ch)){
			pos = i;
			break;
		}
	}
	return pos;
}



static int special_handling_for_compatibility(kk_map_dev_node_t *devNode,cJSON *opcode,cJSON *arg,cJSON **outVal)
{
	int oType = 0;
	int ret = -1;
	
	if(devNode == NULL ||opcode==NULL||arg==NULL){
		return -1;
	}
	oType = atoi(devNode->opearteType);

	if(oType>=14001&&oType<=14500){
		debug_log(LOG_WARNING_LEVEL,"[err]v\n");
		if(!strcmp(opcode->valuestring,"FRESH_AIR_SPEED_SET")){
			debug_log(LOG_WARNING_LEVEL,"[err]a\n");
			if(arg->type==cJSON_String){
				debug_log(LOG_WARNING_LEVEL,"[err]aa\n");
				if(!strcmp(arg->valuestring,"STOP")||
					!strcmp(arg->valuestring,"0")){
					*outVal = cJSON_CreateNumber(0);
					ret = 0;
					debug_log(LOG_WARNING_LEVEL,"[err]0\n");
				}else if(!strcmp(arg->valuestring,"LOW")||
					!strcmp(arg->valuestring,"1")){
					*outVal = cJSON_CreateNumber(1);
					ret = 0;
					debug_log(LOG_WARNING_LEVEL,"[err]1\n");
				}else if(!strcmp(arg->valuestring,"MID")||
					!strcmp(arg->valuestring,"2")){
					*outVal = cJSON_CreateNumber(2);
					ret = 0;
					debug_log(LOG_WARNING_LEVEL,"[err]2\n");
				}else if(!strcmp(arg->valuestring,"HIGH")||
					!strcmp(arg->valuestring,"3")){
					*outVal = cJSON_CreateNumber(3);
					ret = 0;
					debug_log(LOG_WARNING_LEVEL,"[err]3\n");
				}else{
					debug_log(LOG_WARNING_LEVEL,"[err]para:%s\n",arg->valuestring);
				}
			}
			
		}
	}
	
	return ret;
}


cJSON * kk_control_protocol_convert(kk_map_dev_node_t *devNode,int nodeId,cJSON *arg,cJSON *opcode)
{
	cJSON *params = cJSON_CreateObject();
	cJSON *val;

	cJSON *newccuItem;
	cJSON *oldccuItem;

	cJSON *o_dataType;
	cJSON *n_dataType;

	cJSON *n_valueRange;
	cJSON *o_valueRange;

	cJSON *n_identifier;
	cJSON *epNum;

	int pos;
	int channel;
	char ch[33];
	
	
	if(strcmp(opcode->valuestring,"MOVE_TO_POS") == 0 && strcmp(devNode->syn_opcode,"DOOYA_STATUS") == 0){
		if(arg->type == cJSON_String){
			kk_record_motorPosition(atoi(arg->valuestring));
		}
	}
	kk_lan_db_channel_get(nodeId,&channel);
	
	snprintf(ch,33,"%d",channel);

	pos = match_opcode_pos(devNode->oldccu,opcode->valuestring,channel);

	if(pos==-1){
		debug_log(LOG_CRIT_LEVEL,"not find\n");
		cJSON_Delete(params);
		return NULL;
	}
	newccuItem = cJSON_GetArrayItem(devNode->newccu,pos);
	oldccuItem = cJSON_GetArrayItem(devNode->oldccu,pos);

	o_dataType = cJSON_GetObjectItem(oldccuItem,"dataType");
	o_valueRange = cJSON_GetObjectItem(oldccuItem,"valueRange");
	n_dataType = cJSON_GetObjectItem(newccuItem,"dataType");
	n_valueRange = cJSON_GetObjectItem(newccuItem,"valueRange");
	n_identifier =  cJSON_GetObjectItem(newccuItem,"identifier");
	epNum =  cJSON_GetObjectItem(newccuItem,"channel");

	if(special_handling_for_compatibility(devNode,opcode,arg,&val)!=0){
		if(strcmp(o_dataType->valuestring,"map")==0){
		
			val = map_type_convert(o_dataType,o_valueRange,arg,n_valueRange);
		}else{
			val = msg_convert_value(n_dataType,o_dataType,arg);
		}
	}
	

	cJSON_AddStringToObject(params,"epNum",epNum->valuestring);
	debug_log(LOG_WARNING_LEVEL,"[err]val->type:%d\n",val->type);

	if(val->type==cJSON_False){
		cJSON_AddFalseToObject(params,n_identifier->valuestring);
	}else if(val->type==cJSON_True){
		cJSON_AddTrueToObject(params,n_identifier->valuestring);
	}else if(val->type==cJSON_NULL){
		cJSON_AddNullToObject(params,n_identifier->valuestring);
	}else if(val->type==cJSON_Number){
		cJSON_AddNumberToObject(params,n_identifier->valuestring,val->valuedouble);
	}else if(val->type==cJSON_String){
		cJSON_AddStringToObject(params,n_identifier->valuestring,val->valuestring);
	}else if(val->type==cJSON_Array){
		printf("......................\n");
	}

	return params;
}
static int kk_guard_ctrl_handle(int status)
{
	char ccuid[33]={0};
	char pid[33]={0};
	kk_lan_get_ccuid(ccuid);
	kk_lan_get_pid(pid);
	cJSON *root = cJSON_CreateObject();
	cJSON *params = cJSON_CreateObject();
	cJSON_AddStringToObject(params,"epNum","1");
	if(status == 0){ //Àë¼Ò
		cJSON_AddStringToObject(params,"ArmingState","0");
	}else if(status == 2){ //ÔÚ¼Ò
		cJSON_AddStringToObject(params,"ArmingState","2");
	}else{ //³··À
		cJSON_AddStringToObject(params,"ArmingState","1");
	}
	cJSON *info = property_info_build("/thing/service/property/set",pid,ccuid);
	cJSON *payload = property_payload_build("thing.service.property.set","1","v1.0",params);
	cJSON_AddItemToObject(root,INFO_STRING,info);
	cJSON_AddItemToObject(root,PAYLOAD_STRING,payload);
	kk_ipc_send_json(root);
	return 0;
}
static int kk_client_report_handle(cJSON *arg)
{
	char ccuid[33]={0};
	char pid[33]={0};
	if(arg == NULL){
		return -1;
	}
	char* pData = cJSON_Print(arg);
	kk_lan_get_ccuid(ccuid);
	kk_lan_get_pid(pid);
	cJSON *root = cJSON_CreateObject();
	cJSON *info = property_info_build("/thing/service/clientReport",pid,ccuid);
	cJSON *payload = property_payload_build("thing.service.clientReport","1","v1.0",cJSON_Parse(pData));
	cJSON_AddItemToObject(root,INFO_STRING,info);
	cJSON_AddItemToObject(root,PAYLOAD_STRING,payload);
	//printf("----------------------------------------DEBUG-------------------------[%s][%d]\n",__FUNCTION__,__LINE__);
	kk_ipc_send_json(root);
	//printf("----------------------------------------DEBUG-------------------------[%s][%d]\n",__FUNCTION__,__LINE__);
	free(pData);
	return 0;
}
static int kk_get_client_info_handle(cJSON *arg)
{
	char ccuid[33]={0};
	char pid[33]={0};
	if(arg == NULL){
		return -1;
	}
	char* pData = cJSON_Print(arg);
	kk_lan_get_ccuid(ccuid);
	kk_lan_get_pid(pid);
	cJSON *root = cJSON_CreateObject();
	cJSON *info = property_info_build("/thing/service/getClientInfo",pid,ccuid);
	cJSON *payload = property_payload_build("thing.service.getClientInfo","1","v1.0",cJSON_Parse(pData));
	cJSON_AddItemToObject(root,INFO_STRING,info);
	cJSON_AddItemToObject(root,PAYLOAD_STRING,payload);
	kk_ipc_send_json(root);
	free(pData);
	return 0;
}
static int kk_indoorAir_ctrl_handle(char *epNum,cJSON *arg)
{
	kk_map_dev_node_t *dev = NULL;
	if(arg == NULL || epNum == NULL){
		return -1;
	}
	char deviceCode[33]={0};
	cJSON *root = cJSON_CreateObject();
	cJSON *params = cJSON_CreateObject();
	cJSON_AddStringToObject(params,"epNum",epNum);
	cJSON *on = cJSON_GetObjectItem(arg,"on");
	if(on == NULL) return -1;
	cJSON_AddNumberToObject(params,"PowerSwitch",on->valueint);
	cJSON *fanSpeed = cJSON_GetObjectItem(arg,"fanSpeed");
	if(fanSpeed == NULL) return -1;
	if(strcmp(fanSpeed->valuestring,"HIGH") == 0){
		cJSON_AddNumberToObject(params,"WindSpeed",4);
	}else if(strcmp(fanSpeed->valuestring,"MID") == 0){
		cJSON_AddNumberToObject(params,"WindSpeed",3);
	}else if(strcmp(fanSpeed->valuestring,"LOW") == 0){
		cJSON_AddNumberToObject(params,"WindSpeed",2);
	}else{
		cJSON_AddNumberToObject(params,"WindSpeed",0);
	}
	cJSON *settingTemperature = cJSON_GetObjectItem(arg,"settingTemperature");
	if(settingTemperature == NULL) return -1;
	cJSON_AddNumberToObject(params,"Temperature",settingTemperature->valuedouble);
	cJSON *runModel = cJSON_GetObjectItem(arg,"runModel");
	if(runModel == NULL) return -1;
	if(strcmp(runModel->valuestring,"COLD") == 0){
		cJSON_AddNumberToObject(params,"WorkMode",1);
	}else if(strcmp(runModel->valuestring,"HOT") == 0){
		cJSON_AddNumberToObject(params,"WorkMode",2);
	}else if(strcmp(runModel->valuestring,"AIR_SUPPLY") == 0){
		cJSON_AddNumberToObject(params,"WorkMode",3);
	}else if(strcmp(runModel->valuestring,"AUTO") == 0){
		cJSON_AddNumberToObject(params,"WorkMode",0);
	}else if(strcmp(runModel->valuestring,"DEHUMIDIFICATION") == 0){
		cJSON_AddNumberToObject(params,"WorkMode",4);
	}else{
		cJSON_AddNumberToObject(params,"WorkMode",0);
	}
	if(kk_map_dev_search_by_productCode("3062", &dev)!=0){
		printf("kk_indoorAir_ctrl_handle get deviceCode error!!!");
		return -1;
	}
	cJSON *info = property_info_build("/thing/service/property/set","3062",dev->deviceCode);
	cJSON *payload = property_payload_build("thing.service.property.set","1","v1.0",params);
	cJSON_AddItemToObject(root,INFO_STRING,info);
	cJSON_AddItemToObject(root,PAYLOAD_STRING,payload);
	kk_ipc_send_json(root);
	return 0;
}


int kk_lan_ctrl_ack(cJSON * nodeId,cJSON * opcode,cJSON * arg)
{
	cJSON *msg = NULL;
	cJSON *tmp_nodeId = NULL,*tmp_opcode = NULL,*tmp_arg = NULL;
	char *pData = NULL;
	char acData[512] = {0};
	
	if(nodeId==NULL||opcode==NULL||arg==NULL) {
		return -1;
	}

	
	msg=cJSON_CreateObject();
	if(msg){
		memset(acData,0,sizeof(acData));
		pData = cJSON_Print(nodeId);
		snprintf(acData,sizeof(acData),"%s",pData);
		free(pData);
		tmp_nodeId = cJSON_Parse(acData);
		if(tmp_nodeId==NULL){
			cJSON_Delete(msg);
			return -1;
		}
		
		memset(acData,0,sizeof(acData));
		pData = cJSON_Print(opcode);
		snprintf(acData,sizeof(acData),"%s",pData);
		free(pData);
		tmp_opcode = cJSON_Parse(acData);
		if(tmp_opcode==NULL){
			cJSON_Delete(msg);
			return -1;
		}
		
		memset(acData,0,sizeof(acData));
		pData = cJSON_Print(arg);
		snprintf(acData,sizeof(acData),"%s",pData);
		free(pData);
		tmp_arg = cJSON_Parse(acData);
		if(tmp_arg==NULL){
			cJSON_Delete(msg);
			return -1;
		}	
		cJSON_AddItemToObject(msg, "nodeid", tmp_nodeId);
		cJSON_AddItemToObject(msg, "opcode", tmp_opcode);
		cJSON_AddStringToObject(msg, "status", "success");
		cJSON_AddItemToObject(msg, "arg", tmp_arg);
		//cJSON_AddStringToObject(msg, "ack", "true");
	}

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

}
int kk_ccu_opcode_handle(cJSON *root)
{
	cJSON *msg;

	cJSON *nodeId;
	cJSON *opcode;
	cJSON *arg;
	cJSON *requester;
	char deviceCode[33]={0};

	kk_map_dev_node_t *dev;
	nodeId = cJSON_GetObjectItem(root,NODEID_STR);
	opcode = cJSON_GetObjectItem(root,OPCODE_STR);
	arg = cJSON_GetObjectItem(root,ARG_STR);
	
	requester= cJSON_GetObjectItem(root,REQUEST_STR);
	if(opcode==NULL||opcode->type!=cJSON_String){
		return -1;
	}
	if(nodeId==NULL||opcode==NULL||arg==NULL ){
		return -1;
	}
	if(requester!=NULL){
		WARNING_PRINT("[requester]%s\n",requester->valuestring);
		if(strcmp(requester->valuestring,"HJ_CentralAC") == 0 &&
			strcmp(opcode->valuestring,"CENTRAL_AC_INDOOR_UNIT_SETTING") == 0){
			int channel = -1;
			char epNum[8] = {0};
			
			kk_lan_db_channel_get(atoi(nodeId->valuestring),&channel);
			snprintf(epNum,sizeof(epNum),"%d",channel);
			kk_indoorAir_ctrl_handle(epNum,arg);
			return 0;
		}else if(strcmp(requester->valuestring,"HJ_Server") == 0){
			if(strcmp(opcode->valuestring,"ARMING_IN_HOME") == 0){
				kk_guard_ctrl_handle(2);
				return 0;
			}else if(strcmp(opcode->valuestring,"ARMING_LEAVE_HOME") == 0){
				kk_guard_ctrl_handle(0);
				return 0;
			}else if(strcmp(opcode->valuestring,"DISARMING") == 0){
				kk_guard_ctrl_handle(1);
				return 0;
			}else if(strcmp(opcode->valuestring,"CCU_CLIENT_REPORT") == 0){
				kk_client_report_handle(arg);
				return 0;
			}else if(strcmp(opcode->valuestring,GET_CCU_CLIENT_INFO) == 0){
				kk_get_client_info_handle(arg);
				return 0;			
			}
		}
	}

	kk_lan_db_deviceCode_get(atoi(nodeId->valuestring),deviceCode);
	//execute scene
	if((requester!=NULL) &&(strcmp(requester->valuestring,HJ_PROFILE)==0) &&
		(strcmp(opcode->valuestring,"SWITCH")==0)){
		msg=scene_execute(nodeId->valuestring);
		kk_ipc_send_json(msg);
		return 0;

	}

	if(kk_map_dev_search_by_deviceCode(deviceCode, &dev)==0){
		kk_lan_ctrl_ack(nodeId,opcode,arg);
		cJSON *params=kk_control_protocol_convert(dev,atoi(nodeId->valuestring),arg,opcode);
	
		msg=property_set(dev->productCode,dev->deviceCode,"*","*",params);
		kk_ipc_send_json(msg);
		debug_log(LOG_INFO_LEVEL,"MARK!\n");
		
	}else{
		WARNING_PRINT("[%s][%d]\n",__FUNCTION__,__LINE__);
	}
	return 0;
}


































