#include "kk_test.h"
#include "kk_sub_tsl.h"
#include "kk_tsl_zigbee_map.h"

extern kk_tsl_zigbee_map_t g_tsl_zigbee_map [];

static void kk_rpc_send_message(cJSON *data,char *msgtype,char *method,EmberEUI64 mac)
{
	static uint16_t msgid;
	char msgIdString[10]= {0};
	char macString[19] = {0};

	cJSON *info = rpc_cJSON_CreateObject();
	if(info != NULL){
		
		rpc_cJSON_AddStringToObject(info, "msgType",msgtype);
		rpc_cJSON_AddStringToObject(info, "productCode","2");
		rpc_eui64ToString(mac,macString);
		rpc_cJSON_AddStringToObject(info, "deviceCode",macString);	
	}
	cJSON *payload = rpc_cJSON_CreateObject();
	if(payload != NULL){
		sprintf(msgIdString,"%d",++msgid);
		rpc_cJSON_AddStringToObject(payload, "msgId",msgIdString);
		rpc_cJSON_AddStringToObject(payload, "version", KK_IPC_VERSION);
		rpc_cJSON_AddStringToObject(payload, "method",method);
		rpc_cJSON_AddItemToObject(payload, "params", data);		
	}
	cJSON *root = rpc_cJSON_CreateObject();
	if(root != NULL){
		rpc_cJSON_AddItemToObject(root, "info", info);	
		rpc_cJSON_AddItemToObject(root, "payload", payload);	
	}

	char* p = rpc_cJSON_Print(root);
	emberAfAppPrintln("send json:\n%s\n",p);
	free(p);
	jrpc_send_msg(root);	
	rpc_cJSON_Delete(root);	
}
void kk_rpc_report_devices(cJSON *data,EmberEUI64 mac)
{
	kk_rpc_send_message(data,KK_REPORT_DEVICE_JOINED_TYPE,KK_REPORT_DEVICE_JOINED_METHOD,mac);
}
void kk_rpc_report_left_devices(cJSON *data,EmberEUI64 mac)
{
	kk_rpc_send_message(data,KK_REPORT_DEVICE_LEFT_TYPE,KK_REPORT_DEVICE_LEAVE_METHOD,mac);
}

void kk_rpc_report_status(cJSON *data,EmberEUI64 mac)
{

	kk_rpc_send_message(data,KK_REPORT_ATTRIBUTE_TYPE,KK_REPORT_ATTRIBUTE_METHOD,mac);
}

typedef struct{
	EmberEUI64 mac;
	uint8_t AppVersion;
	uint8_t deviceType;
	uint8_t deviceCode;
	uint8_t productType;
	uint8_t productCode;
}kk_report_device_s;

void kk_rpc_reportLeftDevices(EmberEUI64 mac)
{
	cJSON* devicesJson;
	//EmberEUI64 testMac = {0x4A,0x83,0xD3,0xFE,0xFF,0x81,0x8E,0x58}; 
	EmberEUI64 testMac_GW = {0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11}; 
	char macString[RPC_EUI64_STRING_LENGTH];

	printf("[%s][%d]\n",__FUNCTION__,__LINE__);
	devicesJson = rpc_cJSON_CreateObject();
	rpc_eui64ToString(mac,macString);
	printf("[%s][%d]\n",__FUNCTION__,__LINE__);

	rpc_cJSON_AddStringToObject(devicesJson, "productCode",TEST_PRODUCT_CODE);
	rpc_cJSON_AddStringToObject(devicesJson, "deviceCode",macString);
	
	kk_rpc_report_left_devices(devicesJson,testMac_GW);
	kk_sub_tsl_delete(mac);
}

int kk_sendData2CCU(char* data, int len){
    if (strcmp(GW2CCU_PROTOCOL,"tcp") == 0 ){
        kk_tcp_client_send(data, len);
    }else{
        kk_ipc_send(IPC_PLAT2MID, data, len);
    }
}

void kk_rpc_reportDevices(EmberEUI64 mac)
{
	cJSON* devicesJson;
	//EmberEUI64 testMac = {0x4A,0x83,0xD3,0xFE,0xFF,0x81,0x8E,0x58}; 
	EmberEUI64 testMac_GW = {0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11}; 
	char macString[19] = {0};

	devicesJson = rpc_cJSON_CreateObject();
	rpc_eui64ToString(mac,macString);
	rpc_cJSON_AddStringToObject(devicesJson, "productCode",TEST_PRODUCT_CODE);
	rpc_cJSON_AddStringToObject(devicesJson, "deviceCode",macString);
	rpc_cJSON_AddStringToObject(devicesJson, "mac",macString);
	kk_sub_tsl_add(mac,TEST_PRODUCT_CODE);
	kk_rpc_report_devices(devicesJson,testMac_GW);
}


int kk_rpc_report_attribute_status(EmberEUI64 mac,uint8_t EP,int status,uint16_t clusterId,uint16_t attributeId)
{
	cJSON* root;
	int res = 0;
	int num = 0;
	int pCtrlIdx = 0;
	uint8_t endpoint_tmp = 0;
	uint16_t clusterId_tmp = 0;
	uint16_t attributeId_tmp = 0;
	int i = 0;
	sub_dev_node_t *node = NULL;
	char macString[RPC_EUI64_STRING_LENGTH];
	rpc_eui64ToString(mac,macString);

	root = rpc_cJSON_CreateObject();

	res = kk_sub_tsl_get_device_by_mac(macString, &node);
	if (res != SUCCESS_RETURN) {
		printf("[%s][%d]\n",__FUNCTION__,__LINE__);
		return -1;
	}	
	pCtrlIdx = kk_find_ctrl_obj(node->productCode);
	if(pCtrlIdx == -1){
		printf("[%s][%d]\n",__FUNCTION__,__LINE__);		
		return -1;
	}
	num = kk_get_Identity_Num(pCtrlIdx);
	for(i = 0; i < num; i++)
	{
		clusterId_tmp = g_tsl_zigbee_map[pCtrlIdx].zigbee_ctrl[i].clusterId;
		attributeId_tmp = g_tsl_zigbee_map[pCtrlIdx].zigbee_ctrl[i].attributeId;
		endpoint_tmp = g_tsl_zigbee_map[pCtrlIdx].zigbee_ctrl[i].endpoint;
		if(endpoint_tmp == EP &&
			clusterId_tmp == clusterId && 
			attributeId_tmp == attributeId)
		{
			rpc_cJSON_AddNumberToObject(root, g_tsl_zigbee_map[pCtrlIdx].zigbee_ctrl[i].Identity,status);
			break;
		}
	}
	kk_rpc_report_status(root,mac);
	return 0;
}
int kk_zcl_onoff_set(jrpc_context * ctx,const char *mac,unsigned char ep,void* data)
{
	uint8_t eui64[EUI64_SIZE];
    uint8_t OnOffStatus	= 0;
	EmberStatus status = 0;
	EmberNodeId node = 0xffff;

	OnOffStatus = *(uint8_t*)data;
	bool macMatch= rpc_get_mac(mac,eui64);
	emberAfCorePrintBuffer(eui64,EUI64_SIZE,true);
	for(int i=0;i<EUI64_SIZE;i++){
		emberAfCorePrintln("i=%d,val=%02x",i,eui64[i]);
	}


	if(macMatch){
		node = emberAfDeviceTableGetNodeIdFromEui64(eui64);
		if(node==0xffff){
			emberAfCorePrintln("\r\n not find device by node!\r\n" );
			if(ctx)
				set_json_error_type(ctx,JRPC_INVALID_PARAMS,MSG_INVALID_PARAMS);
			goto error_return;
		}
		emberAfCorePrintln("\r\nnode=0x%02X,ep=%d,OnOffStatus=%d\r\n",node,ep,OnOffStatus);

		if(OnOffStatus==1){
			status = zclOnOff_On(node,ep);
			emberAfCorePrintln("\r\nzclOnOff_On\r\n" );
		}else if(OnOffStatus==0){
			status = zclOnOff_Off(node,ep);
			emberAfCorePrintln("\r\nzclOnOff_Off\r\n" );
		}else{
			if(ctx)
				set_json_error_type(ctx,JRPC_INVALID_PARAMS,MSG_INVALID_PARAMS);
			goto error_return;
		}
	}else{
		emberAfCorePrintln("\r\n not find device by mac!\r\n" );
		if(ctx)
			set_json_error_type(ctx,JRPC_INVALID_PARAMS,MSG_INVALID_PARAMS);
		goto error_return;
	}	
	return status;
error_return:
	return -1;
}
#if 0
int kk_test_fuc(char *mac,const char *params)
{
    sub_dev_node_t *node = NULL;
	int res = 0;
	int pCtrlIdx = 0;	
	int num  =0;
	int index = 0;
	cJSON *propertyItem = NULL;
	cJSON *root;	
	root=cJSON_Parse((char*)params);
	res = kk_sub_tsl_get_device_by_mac(mac, &node);
	if (res != SUCCESS_RETURN) {
		printf("[%s][%d]\n",__FUNCTION__,__LINE__);
	
	}
	printf("[%s][%d]node->product_type:%s\n",__FUNCTION__,__LINE__,node->product_type);
	pCtrlIdx = kk_find_ctrl_obj(node->product_type);
	if(pCtrlIdx == -1){
		printf("[%s][%d]\n",__FUNCTION__,__LINE__);		
	}
	printf("[%s][%d]\n",__FUNCTION__,__LINE__);
	num = kk_get_Identity_Num(pCtrlIdx);
	printf("[%s][%d]\n",__FUNCTION__,__LINE__);
	for(index = 0; index < num; index++){
		printf("[%s][%d]\n",__FUNCTION__,__LINE__);
		printf("[%s][%d]------->%s\n",__FUNCTION__,__LINE__,g_tsl_zigbee_map[pCtrlIdx].zigbee_ctrl[index].Identity);
		//kk_sub_tsl_get_Identifier_by_index(mac,index,&identifier);
		propertyItem = rpc_cJSON_GetObjectItem(root, g_tsl_zigbee_map[pCtrlIdx].zigbee_ctrl[index].Identity);
		printf("[%s][%d]\n",__FUNCTION__,__LINE__);
		if(propertyItem != NULL)
		{
			int value = rpc_get_u8(propertyItem->valuestring);
			printf("[%s][%d]value:%d\n",__FUNCTION__,__LINE__,value);
			res = g_tsl_zigbee_map[pCtrlIdx].zigbee_ctrl[index].zigbee_set(NULL,mac,&value);
			if(res < 0)
{
				printf("[%s][%d]\n",__FUNCTION__,__LINE__);
				return -1;
			}
			else{
				printf("[%s][%d]\n",__FUNCTION__,__LINE__);
				return 0;
			}
		}
	}	
	return 0;

}
#endif
cJSON *rpc_read_attribue(jrpc_context * ctx, cJSON *params, cJSON *id,cJSON *mac)
{
	rpc_nwk_info_s info;
	EmberStatus status;
	int num = 0,index = 0;
    cJSON *propertyItem = NULL;
    sub_dev_node_t *node = NULL;
	int pCtrlIdx = 0;
	int res = 0,ret = 0;
	if(params == NULL){
		emberAfCorePrintln("\r\nparams == NULL\r\n" );
		set_json_error_type(ctx,JRPC_INVALID_PARAMS,MSG_INVALID_PARAMS);
		goto error_return;
	}else{
		res = kk_sub_tsl_get_device_by_mac(mac->valuestring, &node);
		if (res != SUCCESS_RETURN) {
			goto error_return;

		}
		pCtrlIdx = kk_find_ctrl_obj(node->productCode);
		if(pCtrlIdx < SUCCESS_RETURN){
			goto error_return;
		}		
		num = kk_get_Identity_Num(pCtrlIdx);		
		for(index = 0; index < num; index++){
			
			propertyItem = rpc_cJSON_GetObjectItem(params, g_tsl_zigbee_map[pCtrlIdx].zigbee_ctrl[index].Identity);
			if(propertyItem != NULL)
			{
				int value = rpc_get_u8(propertyItem->valuestring);
				res = g_tsl_zigbee_map[pCtrlIdx].zigbee_ctrl[index].zigbee_set(ctx,mac->valuestring,g_tsl_zigbee_map[pCtrlIdx].zigbee_ctrl[index].endpoint,&value);
				if(ret < 0)
{
					goto error_return;
				}
				else{
					return rpc_cJSON_CreateNumber(ret);
				}
				
			}
		}
	}
error_return:
	return rpc_cJSON_CreateNull();

}


cJSON *rpc_Control(jrpc_context * ctx, cJSON *params, cJSON *id,cJSON *mac)
{
    sub_dev_node_t *node = NULL;
	int res = 0;
	int num = 0;
	int pCtrlIdx = 0;	
	rpc_nwk_info_s info;
	EmberStatus status;
	int index = 0;
    cJSON *propertyItem = NULL;

	if(params == NULL){
		emberAfCorePrintln("\r\nparams == NULL\r\n" );
		set_json_error_type(ctx,JRPC_INVALID_PARAMS,MSG_INVALID_PARAMS);
		goto error_return;
	}else{
		res = kk_sub_tsl_get_device_by_mac(mac->valuestring, &node);
		if (res != SUCCESS_RETURN) {
			printf("[%s][%d]\n",__FUNCTION__,__LINE__);
			set_json_error_type(ctx,JRPC_INVALID_PARAMS,MSG_INVALID_PARAMS);
			goto error_return;
		}
		pCtrlIdx = kk_find_ctrl_obj(node->productCode);
		if(pCtrlIdx == -1){
			printf("[%s][%d]\n",__FUNCTION__,__LINE__);
			set_json_error_type(ctx,JRPC_INVALID_PARAMS,MSG_INVALID_PARAMS);
			goto error_return;
		}
		num = kk_get_Identity_Num(pCtrlIdx);
		for(index = 0; index < num; index++){	
			propertyItem = rpc_cJSON_GetObjectItem(params, g_tsl_zigbee_map[pCtrlIdx].zigbee_ctrl[index].Identity);
			if(propertyItem != NULL)
			{		
				int value = 0;
				if(propertyItem->type != cJSON_Number){
					value = rpc_get_u8(propertyItem->valuestring);
				}else{
					value = propertyItem->valueint;
				}
				
				res = g_tsl_zigbee_map[pCtrlIdx].zigbee_ctrl[index].zigbee_set(ctx,mac->valuestring,g_tsl_zigbee_map[pCtrlIdx].zigbee_ctrl[index].endpoint,&value);
				if(res < 0)
				{
					set_json_error_type(ctx,JRPC_INVALID_PARAMS,MSG_INVALID_PARAMS);
					goto error_return;
				}
				else{
					return rpc_cJSON_CreateNumber(res);
				}			
			}
		}
	}
error_return:
	return rpc_cJSON_CreateNull();
}

int rpc_nwkPermitJoin(jrpc_context * ctx,const char *mac,unsigned char ep,void* data)
{
	EmberStatus status;
	uint8_t isEnable = *(uint8_t*)data;

	if(isEnable == 0){
		status = nwkPermitJoinCMD(FALSE);
		emberAfCorePrintln("Disable Permit join\r\n");
	}else if(isEnable == 1){
		status = nwkPermitJoinCMD(TRUE);
		emberAfCorePrintln("Enable Permit join %ds\r\n",EMBER_AF_PLUGIN_NETWORK_CREATOR_SECURITY_NETWORK_OPEN_TIME_S);
	}else{
		set_json_error_type(ctx,JRPC_INVALID_PARAMS,MSG_INVALID_PARAMS);
		goto error_return;
	}

	return status;
	
error_return:
	return -1;

}





void emberAfPluginDeviceTableNewDeviceCallback(EmberEUI64 nodeEui64)
{
	uint16_t deviceTableIndex = emberAfDeviceTableGetFirstIndexFromEui64(nodeEui64);
	if(deviceTableIndex == 0xffff){
		kk_print_info("not find item!");
		return ;
	}

	EmberAfPluginDeviceTableEntry *deviceTable = emberAfDeviceTablePointer();

	//cJSON* nodeJson = rpc_reportDeviceState("joined",deviceTable[deviceTableIndex].eui64);
	//rpc_printfJSON("joined",nodeJson);
	//rpc_send_message(nodeJson,"device joined");

	//rpc_add_device(deviceTable[deviceTableIndex].nodeId);

	//kk_report_device_s device;
	//device.mac = nodeEui64;
	//device.AppVersion = 0x10;
	//memcpy(device.mac,nodeEui64,EUI64_SIZE);
	kk_rpc_reportDevices(deviceTable[deviceTableIndex].eui64);
}







int kk_report_global_onoff_attribute(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data)
{
	uint8_t OnOff;
	if(dataType == ZCL_BOOLEAN_ATTRIBUTE_TYPE){
		if(len==1){
			OnOff = data[0];
			if(OnOff==0||OnOff==1){//todo:
				kk_rpc_report_attribute_status(eui64,EP,OnOff,clusterId,attributeId);
				return 0;
			}
			return -1;
		}
		return -2;
	}
	return -3;
}


enum {
	WC_normal_dir								= 0,//"正转"
	WC_reversed_dir								= 1,//"反转"
	WC_calibration_mode							= 2,//"校验"
}windowCoveringMode;
int kk_report_windowCovering_mode_attribute(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data)
{
	uint8_t mode;
	if(dataType == ZCL_BITMAP8_ATTRIBUTE_TYPE){
		if(len==1){
			if(data[0]&BIT(1)){
				mode = WC_calibration_mode;
			}else if(data[0]&BIT(0)){
				mode = WC_reversed_dir;
			}else{
				mode = WC_normal_dir;
			}

			kk_rpc_report_attribute_status(eui64,EP,mode,clusterId,attributeId);
			return 0;
		}
		return -2;
	}
	return -3;
}
int kk_report_windowCovering_position_attribute(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data)
{
	uint8_t position;
	if(dataType == ZCL_INT16U_ATTRIBUTE_TYPE){
		if(len==2){
			position = HIGH_LOW_TO_INT(data[1], data[0]);
			kk_rpc_report_attribute_status(eui64,EP,position,clusterId,attributeId);
			return 0;
		
		}
		return -2;
	}
	return -3;
}


typedef int(*kk_rpc_report_attr_func)(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data);
typedef struct{
	EmberAfClusterId clusterId;
	EmberAfAttributeId attributeId;
	kk_rpc_report_attr_func func;
}kk_rpc_report_map_s;

static kk_rpc_report_map_s kk_report_map[]={
	{ZCL_ON_OFF_CLUSTER_ID,ZCL_ON_OFF_ATTRIBUTE_ID,kk_report_global_onoff_attribute},
	{ZCL_WINDOW_COVERING_CLUSTER_ID,ZCL_MODE_ATTRIBUTE_ID,kk_report_windowCovering_mode_attribute},
	{ZCL_WINDOW_COVERING_CLUSTER_ID,ZCL_CURRENT_LIFT_ATTRIBUTE_ID,}
};
	

void kk_dispatch_report_attribute(EmberEUI64 eui64,
									uint8_t EP,
									EmberAfClusterId clusterId,
									EmberAfAttributeId attributeId,
									uint8_t dataType,
									uint8_t len,
									uint8_t *data)
{
	int i,num,result;
	num = sizeof(kk_report_map)/sizeof(kk_rpc_report_map_s);
	kk_rpc_report_map_s *report_item = kk_report_map;
	for(i=0;i<num;i++,report_item++){
		if(report_item->clusterId==clusterId && 
			report_item->attributeId == attributeId){
			result = report_item->func(eui64,EP,clusterId,attributeId,dataType,len,data);
			if(!result){
				emberAfAppPrintln("result=%d",result);
				emberAfAppPrintln("mac:");
				emberAfPrintBigEndianEui64(eui64);
				emberAfAppPrintln(",ep=%d,clu=0x%x,attr=0x%x,type=0x%x,len=%d",EP,clusterId,attributeId,dataType,len);
				emberAfAppPrintBuffer(data,len,true);
			}
			return ;
		}
	}
	emberAfAppPrintln("not find report item!!!ep=%d,clu=0x%x,attr=0x%x\n",EP,clusterId,attributeId);
}

