#include "kk_data_mng.h"
#include "kk_lan_vp_ctrl.h"
#include "kk_lan_debug.h"
#include "cJSON.h"
#include "kk_voice_panel_cfg.h"

typedef cJSON *(*dev_handle_func)(int ep,uint8_t *arg,uint8_t arg_len);

typedef struct {
	const int *pidAry;
	int num;
	dev_handle_func func;
}DEV_PID_S;

static cJSON *air_conditioner_dev_handle(int ep,uint8_t *arg,uint8_t arg_len);

static cJSON *light_dev_handle(int ep,uint8_t *arg,uint8_t arg_len);
static cJSON *curtain_dev_handle(int ep,uint8_t *arg,uint8_t arg_len);
static cJSON *outlet_dev_handle(int ep,uint8_t *arg,uint8_t arg_len);
static cJSON *freshAir_dev_handle(int ep,uint8_t *arg,uint8_t arg_len);
static cJSON *fanCoilSwitch_dev_handle(int ep,uint8_t *arg,uint8_t arg_len);
static cJSON *underfloor_heating_dev_handle(int ep,uint8_t *arg,uint8_t arg_len);
static cJSON *dimming_light_dev_handle(int ep,uint8_t *arg,uint8_t arg_len);

static const int air_conditioner_dev_pid[] = AIR_CONDITIONER_DEV_PID;

static const int light_dev_pid[] = LIGHT_DEV_PID;
static const int curtain_dev_pid[] = CURTAIN_DEV_PID;
static const int outlet_dev_pid[] = OUTLET_DEV_PID;
static const int freshAir_dev_pid[] = FRESHAIR_DEV_PID;
static const int fanCoilSwitch_dev_pid[] = FANCOILSWITCH_DEV_PID;
static const int underfloor_heating_dev_pid[] = UNDERFLOOR_HEATING_DEV_PID;
static const int dimming_light_dev_pid[] = DIMMING_LIGHT_DEV_PID;





static DEV_PID_S g_dev_pid[] = {
	{ light_dev_pid,sizeof(light_dev_pid)/ sizeof(int),light_dev_handle},
	{ curtain_dev_pid,sizeof(curtain_dev_pid) / sizeof(int),curtain_dev_handle},
	{ outlet_dev_pid,sizeof(outlet_dev_pid) / sizeof(int),outlet_dev_handle},
	{ freshAir_dev_pid,sizeof(freshAir_dev_pid) / sizeof(int),freshAir_dev_handle},
	{ fanCoilSwitch_dev_pid,sizeof(fanCoilSwitch_dev_pid) / sizeof(int),fanCoilSwitch_dev_handle},
	{ underfloor_heating_dev_pid,sizeof(underfloor_heating_dev_pid) / sizeof(int),underfloor_heating_dev_handle},
	{ dimming_light_dev_pid,sizeof(dimming_light_dev_pid) / sizeof(int),dimming_light_dev_handle},
};
	
static dev_handle_func dev_pid_dispatch(int pid)
{
	int i,j;
	int num = sizeof(g_dev_pid) / sizeof(DEV_PID_S);
	DEV_PID_S *pDevPid = g_dev_pid;
	
	for (i = 0; i<num ; i++,pDevPid++) {
		for (j = 0; j < pDevPid->num;j++) {
			if(pid==pDevPid->pidAry[j]){
				return pDevPid->func;
			}
		}
	}

	return NULL;
}

//****************************************************************************

cJSON *PowerSwitch_msg_build(int ep,int onoff)
{
	char epNum[12] = {0};
	cJSON *params = cJSON_CreateObject();

	memset(epNum,0,sizeof(epNum));
	snprintf(epNum,sizeof(epNum),"%d",ep);
	cJSON_AddStringToObject(params,"epNum",epNum);
	cJSON_AddNumberToObject(params,"PowerSwitch",onoff);
	return params;
}

static cJSON *windSpeed_msg_build(int ep,int level)
{
	char epNum[12] = {0};
	cJSON *params = cJSON_CreateObject();

	memset(epNum,0,sizeof(epNum));
	snprintf(epNum,sizeof(epNum),"%d",ep);

	cJSON_AddStringToObject(params,"epNum",epNum);
	cJSON_AddNumberToObject(params,"WindSpeed",level);

	return params;
}

static cJSON *workMode_msg_build(int ep,int mode)
{
	char epNum[12] = {0};
	cJSON *params = cJSON_CreateObject();

	memset(epNum,0,sizeof(epNum));
	snprintf(epNum,sizeof(epNum),"%d",ep);

	cJSON_AddStringToObject(params,"epNum",epNum);
	cJSON_AddNumberToObject(params,"WorkMode",mode);

	return params;
}



static cJSON *temperature_msg_build(int ep,int tmp)
{
	char epNum[12] = {0};
	cJSON *params = cJSON_CreateObject();

	memset(epNum,0,sizeof(epNum));
	snprintf(epNum,sizeof(epNum),"%d",ep);

	cJSON_AddStringToObject(params,"epNum",epNum);
	cJSON_AddNumberToObject(params,"Temperature",tmp);

	return params;
}

static cJSON *ColorTemperature_msg_build(int ep,int val)
{
	char epNum[12] = {0};
	cJSON *params = cJSON_CreateObject();

	memset(epNum,0,sizeof(epNum));
	snprintf(epNum,sizeof(epNum),"%d",ep);

	cJSON_AddStringToObject(params,"epNum",epNum);
	cJSON_AddNumberToObject(params,"ColorTemperature",val);

	return params;
}

static cJSON *Brightness_msg_build(int ep,int val)
{
	char epNum[12] = {0};
	cJSON *params = cJSON_CreateObject();

	memset(epNum,0,sizeof(epNum));
	snprintf(epNum,sizeof(epNum),"%d",ep);

	cJSON_AddStringToObject(params,"epNum",epNum);
	cJSON_AddNumberToObject(params,"Brightness",val);

	return params;
}















//****************************************************************************

static cJSON *light_msg_build(int ep,int onoff)
{
	return PowerSwitch_msg_build(ep,onoff);
}



static cJSON *freshAir_msg_build(int ep,int onoff)
{
	return PowerSwitch_msg_build(ep,onoff);
}



//****************************************************************************

static cJSON *air_conditioner_dev_handle(int ep,uint8_t *arg,uint8_t arg_len)
{
	uint8_t skill_type = arg[0];
	
	switch(skill_type){
		case VP_CTRL_OPEN://
			return PowerSwitch_msg_build(ep,1);
		case VP_CTRL_CLOSE:
			return PowerSwitch_msg_build(ep,0);

		case VP_CTRL_WINDSPEE_SET:{
			if(arg[1]!=0x20){
				return NULL;
			}
			uint8_t windspeed = arg[2];
			debug_log(LOG_FOCUS_LEVEL,"[VP] set windspeed=%d\n",windspeed);
			if(windspeed==VP_SKILLTYPE_12_WINDSPEED_LOW){
				return windSpeed_msg_build(ep,2);
			}else if(windspeed==VP_SKILLTYPE_12_WINDSPEED_MID){
				return windSpeed_msg_build(ep,3);
			}else if(windspeed==VP_SKILLTYPE_12_WINDSPEED_HIGH){
				return windSpeed_msg_build(ep,4);
			}
			break;
		}

		case VP_CTRL_MODE:{
			if(arg[1]!=0x20){
				return NULL;
			}
			uint8_t mode = arg[2];
			_debug_log(LOG_FOCUS_LEVEL,"[VP] set mode=%d\n",mode);
			if(mode==VP_SKILLTYPE_1C_WORKMODE_COLD){
				return workMode_msg_build(ep,1);
			}else if(mode==VP_SKILLTYPE_1C_WORKMODE_HEATING){
				return workMode_msg_build(ep,2);
			}else if(mode==VP_SKILLTYPE_1C_WORKMODE_FAN){
				return workMode_msg_build(ep,3);
			}else if(mode==VP_SKILLTYPE_1C_WORKMODE_DEHUM){
				return workMode_msg_build(ep,4);
			}else if(mode==VP_SKILLTYPE_1C_WORKMODE_AUTO){
				return workMode_msg_build(ep,0);
			}
			break;
		}
		
		case VP_CTRL_TMP_SET:
			if(arg[1]!=0x20){
				return NULL;
			}
			uint8_t tmp = arg[2];
			_debug_log(LOG_FOCUS_LEVEL,"[VP] set tmp=%d\n",tmp);
			return temperature_msg_build(ep,tmp);	

		default:break;
	}
	return NULL;
}


static cJSON *light_dev_handle(int ep,uint8_t *arg,uint8_t arg_len)
{
	uint8_t skill_type = arg[0];

	switch(skill_type){
		case VP_CTRL_OPEN://
			return light_msg_build(ep,1);
		case VP_CTRL_CLOSE:
			return light_msg_build(ep,0);
		default:break;
	}
	return NULL;
}




static cJSON *curtain_dev_msg_build(int ep,int OperationMode)
{
	char epNum[12] = {0};
	cJSON *params = cJSON_CreateObject();
	printf("[%s][%d]\n",__FUNCTION__,__LINE__);

	memset(epNum,0,sizeof(epNum));
	snprintf(epNum,sizeof(epNum),"%d",ep);
	printf("[%s][%d]\n",__FUNCTION__,__LINE__);
	cJSON_AddStringToObject(params,"epNum",epNum);
	printf("[%s][%d]\n",__FUNCTION__,__LINE__);
	cJSON_AddNumberToObject(params,"OperationMode",OperationMode);
	printf("[%s][%d]\n",__FUNCTION__,__LINE__);
	return params;
}

static cJSON *curtain_dev_handle(int ep,uint8_t *arg,uint8_t arg_len)
{
	uint8_t skill_type = arg[0];
	debug_log(LOG_FOCUS_LEVEL,"skill_type=%d,ep=%d\n",skill_type,ep);
	switch(skill_type){
		case VP_CTRL_OPEN://
			return curtain_dev_msg_build(ep,1);
		case VP_CTRL_CLOSE:
			return curtain_dev_msg_build(ep,0);
		case VP_CTRL_STOP:
			return curtain_dev_msg_build(ep,2);
		default:break;
	}
	return NULL;
}


static cJSON *outlet_msg_build(int ep,int onoff)
{
	return PowerSwitch_msg_build(ep,onoff);
}


static cJSON *outlet_dev_handle(int ep,uint8_t *arg,uint8_t arg_len)
{
	uint8_t skill_type = arg[0];
	debug_log(LOG_FOCUS_LEVEL,"skill_type=%d,ep=%d\n",skill_type,ep);
	switch(skill_type){
		case VP_CTRL_OPEN://
			return outlet_msg_build(ep,1);
		case VP_CTRL_CLOSE:
			return outlet_msg_build(ep,0);
		default:break;
	}
	return NULL;
}




static cJSON *freshAir_windspeed_msg_build(int ep,int level)
{
	char epNum[12] = {0};
	cJSON *params = cJSON_CreateObject();

	memset(epNum,0,sizeof(epNum));
	snprintf(epNum,sizeof(epNum),"%d",ep);

	cJSON_AddStringToObject(params,"epNum",epNum);
	cJSON_AddNumberToObject(params,"WindSpeed",level);

	return params;
}

static cJSON *freshAir_workMode_msg_build(int ep,int mode)
{
	char epNum[12] = {0};
	cJSON *params = cJSON_CreateObject();

	memset(epNum,0,sizeof(epNum));
	snprintf(epNum,sizeof(epNum),"%d",ep);

	cJSON_AddStringToObject(params,"epNum",epNum);
	cJSON_AddNumberToObject(params,"WorkMode",mode);

	return params;
}



static cJSON *freshAir_dev_handle(int ep,uint8_t *arg,uint8_t arg_len)
{
	uint8_t skill_type = arg[0];

	if(arg_len!=3){
		debug_log(LOG_ERROR_LEVEL,"[err] arg_len=%d\n",arg_len);
		return NULL;
	}
	
	switch(skill_type){
		case VP_CTRL_OPEN://
			return PowerSwitch_msg_build(ep,1);
		case VP_CTRL_CLOSE:
			return PowerSwitch_msg_build(ep,0);

		case VP_CTRL_WINDSPEE_SET:{
			if(arg[1]!=0x20){
				return NULL;
			}
			uint8_t windspeed = arg[2];
			_debug_log(LOG_FOCUS_LEVEL,"[VP] set windspeed=%d\n",windspeed);
			if(windspeed==VP_SKILLTYPE_12_WINDSPEED_LOW){
				return freshAir_windspeed_msg_build(ep,1);
			}else if(windspeed==VP_SKILLTYPE_12_WINDSPEED_MID){
				return freshAir_windspeed_msg_build(ep,2);
			}else if(windspeed==VP_SKILLTYPE_12_WINDSPEED_HIGH){
				return freshAir_windspeed_msg_build(ep,3);
			}
			break;
		}
			
			
		case VP_CTRL_MODE:{
			if(arg[1]!=0x20){
				return NULL;
			}
			uint8_t mode = arg[2];
			_debug_log(LOG_FOCUS_LEVEL,"[VP] set mode=%d\n",mode);
			if(mode==VP_SKILLTYPE_1C_WORKMODE_AUTO){
				return freshAir_workMode_msg_build(ep,0);
			}else if(mode==VP_SKILLTYPE_1C_WORKMODE_MANUAL){
				return freshAir_workMode_msg_build(ep,1);
			}
			break;
		}

		default:break;
	}
	return NULL;
}


static cJSON *fanCoilSwitch_windspeed_msg_build(int ep,int level)
{
	char epNum[12] = {0};
	cJSON *params = cJSON_CreateObject();

	memset(epNum,0,sizeof(epNum));
	snprintf(epNum,sizeof(epNum),"%d",ep);

	cJSON_AddStringToObject(params,"epNum",epNum);
	cJSON_AddNumberToObject(params,"WindSpeed",level);

	return params;
}
static cJSON *fanCoilSwitch_workMode_msg_build(int ep,int mode)
{
	char epNum[12] = {0};
	cJSON *params = cJSON_CreateObject();

	memset(epNum,0,sizeof(epNum));
	snprintf(epNum,sizeof(epNum),"%d",ep);

	cJSON_AddStringToObject(params,"epNum",epNum);
	cJSON_AddNumberToObject(params,"WorkMode",mode);

	return params;
}

static cJSON *fanCoilSwitch_Temperature_msg_build(int ep,int tmp)
{
	char epNum[12] = {0};
	cJSON *params = cJSON_CreateObject();

	memset(epNum,0,sizeof(epNum));
	snprintf(epNum,sizeof(epNum),"%d",ep);

	cJSON_AddStringToObject(params,"epNum",epNum);
	cJSON_AddNumberToObject(params,"Temperature",tmp);

	return params;
}

static cJSON *fanCoilSwitch_dev_handle(int ep,uint8_t *arg,uint8_t arg_len)
{
	uint8_t skill_type = arg[0];
	
	switch(skill_type){
		case VP_CTRL_OPEN://
			return PowerSwitch_msg_build(ep,1);
		case VP_CTRL_CLOSE:
			return PowerSwitch_msg_build(ep,0);

		case VP_CTRL_WINDSPEE_SET:{
			if(arg[1]!=0x20){
				return NULL;
			}
			uint8_t windspeed = arg[2];
			debug_log(LOG_FOCUS_LEVEL,"[VP] set windspeed=%d\n",windspeed);
			if(windspeed==VP_SKILLTYPE_12_WINDSPEED_LOW){
				return fanCoilSwitch_windspeed_msg_build(ep,2);
			}else if(windspeed==VP_SKILLTYPE_12_WINDSPEED_MID){
				return fanCoilSwitch_windspeed_msg_build(ep,3);
			}else if(windspeed==VP_SKILLTYPE_12_WINDSPEED_HIGH){
				return fanCoilSwitch_windspeed_msg_build(ep,4);
			}else if(windspeed==VP_SKILLTYPE_12_WINDSPEED_AUTO){
				return fanCoilSwitch_windspeed_msg_build(ep,0);
			}
			break;
		}
		
		case VP_CTRL_MODE:{
			if(arg[1]!=0x20){
				return NULL;
			}
			uint8_t mode = arg[2];
			_debug_log(LOG_FOCUS_LEVEL,"[VP] set mode=%d\n",mode);
			if(mode==VP_SKILLTYPE_1C_WORKMODE_COLD){
				return freshAir_workMode_msg_build(ep,1);
			}else if(mode==VP_SKILLTYPE_1C_WORKMODE_HEATING){
				return freshAir_workMode_msg_build(ep,2);
			}else if(mode==VP_SKILLTYPE_1C_WORKMODE_FAN){
				return freshAir_workMode_msg_build(ep,3);
			}else if(mode==VP_SKILLTYPE_1C_WORKMODE_DEHUM){
				return freshAir_workMode_msg_build(ep,4);
			}
			break;
		}
		
		case VP_CTRL_TMP_SET:
			if(arg[1]!=0x20){
				return NULL;
			}
			uint8_t tmp = arg[2];
			_debug_log(LOG_FOCUS_LEVEL,"[VP] set tmp=%d\n",tmp);
			return fanCoilSwitch_Temperature_msg_build(ep,tmp);	

		default:break;
	}
	return NULL;
}

static cJSON *underfloor_heating_dev_handle(int ep,uint8_t *arg,uint8_t arg_len)
{
	uint8_t skill_type = arg[0];
	
	switch(skill_type){
		case VP_CTRL_OPEN://
			return PowerSwitch_msg_build(ep,1);
		case VP_CTRL_CLOSE:
			return PowerSwitch_msg_build(ep,0);
		
		case VP_CTRL_MODE:{
			if(arg[1]!=0x20){
				return NULL;
			}
			uint8_t mode = arg[2];
			_debug_log(LOG_FOCUS_LEVEL,"[VP] set mode=%d\n",mode);
			if(mode==VP_SKILLTYPE_1C_WORKMODE_AUTO){
				return workMode_msg_build(ep,0);
			}else if(mode==VP_SKILLTYPE_1C_WORKMODE_MANUAL){
				return workMode_msg_build(ep,1);
			}
			break;
		}
		
		case VP_CTRL_TMP_SET:
			if(arg[1]!=0x20){
				return NULL;
			}
			uint8_t tmp = arg[2];
			_debug_log(LOG_FOCUS_LEVEL,"[VP] set tmp=%d\n",tmp);
			return temperature_msg_build(ep,tmp);	

		default:break;
	}
	return NULL;
}

static cJSON *dimming_light_dev_handle(int ep,uint8_t *arg,uint8_t arg_len)
{
	uint8_t skill_type = arg[0];
	
	switch(skill_type){
		case VP_CTRL_OPEN://
			return PowerSwitch_msg_build(ep,1);
		case VP_CTRL_CLOSE:
			return PowerSwitch_msg_build(ep,0);
		
		case VP_CTRL_SET_COLOR_TMP:{
			if(arg[1]!=0x20){
				return NULL;
			}
			uint8_t mode = arg[2];
			_debug_log(LOG_FOCUS_LEVEL,"[VP] set mode=%d\n",mode);
			if(mode==VP_SKILLTYPE_1C_WORKMODE_AUTO){
				return workMode_msg_build(ep,0);
			}else if(mode==VP_SKILLTYPE_1C_WORKMODE_MANUAL){
				return workMode_msg_build(ep,1);
			}
			break;
		}
		case VP_CTRL_BRIGHTNESS_SET:
			if(arg[1]!=0x20){
				return NULL;
			}
			uint8_t bri = arg[2];
			Brightness_msg_build(ep,bri);
			break;
			
		default:break;
	}
	return NULL;
}


int kk_lan_vp_control(uint8_t num,uint32_t nodeIdAry[],uint8_t *arg,uint8_t arg_len)
{
	uint8_t i,j;
	uint8_t err = 0;
	uint8_t skill_type;
	int ep;
	int pid = 0;
	dev_handle_func func;

	char productCode[PRODUCT_CODE_LEN] = {0};
	char deviceCode[DEVICE_CODE_LEN] = {0};
	

	cJSON *msg = NULL;
	cJSON *params = NULL;
	
	kk_map_dev_node_t *node = NULL;

	if(arg_len<=1){
		debug_log(LOG_ERROR_LEVEL,"[err].\n");
		return 1;
	}
	skill_type = arg[0];


	for(i=0;i<num;i++){
		memset(deviceCode,0,sizeof(deviceCode));
		memset(productCode,0,sizeof(productCode));
		kk_lan_db_deviceCode_get(nodeIdAry[i],deviceCode);
		kk_lan_db_channel_get(nodeIdAry[i],&ep);

		if(kk_map_dev_search_by_deviceCode(deviceCode,&node) != 0){
			continue ;
		}
		
		snprintf(productCode,sizeof(productCode),"%s",node->productCode);


		pid = atoi(productCode);

		params = NULL;

		if(is_ac_gw_pid(pid)!=0){
			debug_log(LOG_FOCUS_LEVEL,"air conditioner,pid=%d\n",pid);
			params = air_conditioner_dev_handle(ep,arg,arg_len);
		}else{
			if((func = dev_pid_dispatch(pid))!=NULL){
				debug_log(LOG_FOCUS_LEVEL,"skill_type=%02x,ep=%d\n",skill_type,ep);
				params = func(ep,arg,arg_len);
			}
		}
		
		if(params!=NULL){
			msg=property_set(productCode,deviceCode,"*","*",params);
			kk_ipc_send_json(msg);
		}else{
			err = 1;
			break;
		}
	}

	return err;
}






















