#include "kk_tsl_property_report.h"
#include "kk_device_manager.h"
#include "kk_rgb_hsl_convert.h"
#include "kk_device_table_db.h"
#include "kk_zigbee_api.h"

const char *kk_tsl_rpt_status_string[] = {
	"Success",
	"Error",
	"Invaild Value",
	"Invaild Len",
	"Invaild Type"
};
//todo: fix it

static cJSON* kk_check_identify(const char * identify,cJSON* root,int index,int status)
{
	int rev = 0,startIdx2 = 0,startIdx1 = 0;
	char *Identify_str;
	char tmp_Identity[64] = {0};	

	rev = kk_tsl_utils_memtok(identify,'.',2,&startIdx2);
	if(!rev){
		cJSON* str = NULL;
		cJSON* str_r = NULL;
		kk_tsl_utils_memtok(identify,'.',1,&startIdx1);
		str = rpc_cJSON_CreateObject();
		Identify_str = identify + 1 + startIdx2;
		memset(tmp_Identity,0x0,sizeof(tmp_Identity));
		memcpy(tmp_Identity,identify+startIdx1+1,startIdx2-startIdx1);
		rpc_cJSON_AddNumberToObject(str, Identify_str,status);
		str_r = rpc_cJSON_CreateObject();
		rpc_cJSON_AddItemToObject(str_r,tmp_Identity,str);
		memset(tmp_Identity,0x0,sizeof(tmp_Identity));
		memcpy(tmp_Identity,identify,startIdx1);		
		rpc_cJSON_AddItemToObject(root,tmp_Identity,str_r);
		return root;
	}
	else{
		rev = kk_tsl_utils_memtok(identify,'.',1,&startIdx1);
		if(!rev){
			cJSON* str = NULL;
			str = rpc_cJSON_CreateObject();
			Identify_str = identify + 1 + startIdx1;
			memset(tmp_Identity,0x0,sizeof(tmp_Identity));
			memcpy(tmp_Identity,identify,startIdx1);
			rpc_cJSON_AddNumberToObject(str, Identify_str,status);
			rpc_cJSON_AddItemToObject(root,tmp_Identity,str);
			return root;
		}		

	}
	return NULL;


}

static int kk_tsl_report(EmberEUI64 mac,uint8_t EP,int status,uint16_t clusterId,uint16_t attributeId)
{
	cJSON* root,*root_tmp;
	int index;
	char *Identify;
	kk_device_table_s *dev;
	kk_dev_config_map *dev_info = NULL;
	kk_dev_config_item *item = NULL;	
	char macString[RPC_EUI64_STRING_LENGTH];

	rpc_eui64ToString(mac,macString);

	root = rpc_cJSON_CreateObject();
	
	dev = kk_device_find_by_mac(mac);	
	if(dev == NULL){
		printf("mac:%s not find in zb dev table!!!\n",macString);
		return tsl_rpt_err;
	}
	printf("[%s][%d]dev->productCode:%s\n",__FUNCTION__,__LINE__,dev->productCode);
	dev_info = kk_device_config_find(dev->productCode);
	if(dev_info == NULL){
		return tsl_rpt_err;
	}	
	item = &dev_info->item;
	if(clusterId==ZCL_IAS_ZONE_CLUSTER_ID && attributeId== ZCL_ZONE_STATUS_ATTRIBUTE_ID){
		while(item!=NULL){
			if(EP == item->endpoint &&
				clusterId == item->cluster&&
				attributeId == item->attribute){
				{
					if(item->iasZoneStatusMask!=0){
						root_tmp = kk_check_identify(Identify,root,index,status);
						if(root_tmp != NULL){
							kk_rpc_report_status(root_tmp,mac);
						}
						else{
							status = ((status&0xffff)&item->iasZoneStatusMask) ? 1 : 0;
							rpc_cJSON_AddNumberToObject(root, Identify,status);
							kk_msg_report_property(root,mac);
						}
					}
				}
			}
			item = item->next;
		}
	}else{
		while(item!=NULL){
			if(EP == item->endpoint &&
				clusterId == item->cluster&&
				attributeId == item->attribute){
				Identify = item->identity;
				break;
			}
			item = item->next;
		}
		root_tmp = kk_check_identify(Identify,root,index,status);
		if(root_tmp != NULL){
			kk_rpc_report_status(root_tmp,mac);
		}
		else{
			if(clusterId==ZCL_BASIC_CLUSTER_ID && attributeId== ZCL_BATTERY_PERCENTAGE_REMAINING_ATTRIBUTE_ID){
				double battery = (double)status * 0.5;
				char batteryStr[32];
				sprintf(batteryStr,"%f",battery);
				rpc_cJSON_AddStringToObject(root, Identify,batteryStr);
			}else{
				rpc_cJSON_AddNumberToObject(root, Identify,status);
			}
			
			kk_msg_report_property(root,mac);
		}
	}
	return tsl_rpt_success;
}


//typedef int(*kk_rpc_report)(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data);
void kk_tsl_report_alarm(EmberEUI64 eui64,
								uint16_t zoneStatus,
								uint8_t extendedStatus,
								uint8_t zoneId,
								uint16_t delay)
{
	cJSON* root;
	kk_device_table_s *dev = NULL;
	kk_dev_config_map *dev_info = NULL;
	kk_dev_config_item *item = NULL;
	kk_rpc_report func;

	UTIL_LOG_INFO("\n********************kk_tsl_report_alarm********************\n");
	dev = kk_device_find_by_mac(eui64); 
	if(dev == NULL){
		return;
	}	
	dev_info = kk_device_config_find(dev->productCode);
	if(dev_info == NULL){
		return;
	}	
	item = &dev_info->item;

	while(item!=NULL){
		
		if(item->cluster== ZCL_IAS_ZONE_CLUSTER_ID
			&& item->attribute ==ZCL_ZONE_STATUS_ATTRIBUTE_ID &&
			item->iasZoneStatusMask!=0 && item->reportFunc==NULL){
			root = rpc_cJSON_CreateObject();
			rpc_cJSON_AddNumberToObject(root, item->identity,(zoneStatus & item->iasZoneStatusMask) ? 1 : 0);
			kk_msg_report_alarm(root,eui64);
			
		}
		
		item = item->next;
	}

}

void kk_tsl_report_attribute(EmberEUI64 eui64,
									uint8_t EP,
									EmberAfClusterId clusterId,
									EmberAfAttributeId attributeId,
									uint8_t dataType,
									uint8_t len,
									uint8_t *data)
{
	int i,j,num,status;	
	int res = 0;
	char macString[RPC_EUI64_STRING_LENGTH];
	kk_device_table_s *dev = NULL;
	kk_dev_config_map *dev_info = NULL;
	kk_dev_config_item *item = NULL;
	kk_rpc_report func;


	UTIL_LOG_INFO("\n********************kk tsl report attribute********************\n");
	emberAfDebugPrintln(",ep:%d,clu:0x%04X,attr:0x%04X,dataType=0x%02x,len=%d,data:",
						EP,clusterId,attributeId,dataType,len);
	emberAfDebugPrintBuffer(data,len,true);
	//rpc_eui64ToString(eui64,macString);	
	dev = kk_device_find_by_mac(eui64);	
	if(dev == NULL){
		return;
	}	

	dev_info = kk_device_config_find(dev->productCode);
	if(dev_info == NULL){
		return;
	}	


	item = &dev_info->item;
	while(item!=NULL){
		if(EP == item->endpoint &&
			clusterId == item->cluster&&
			attributeId == item->attribute){

			func = item->reportFunc;
			if(func != NULL){
				func(eui64,EP,clusterId,attributeId,dataType,len,data);
			}else{

			}
			return;
		}
		item = item->next;
	}	
}


int kk_tsl_report_global_onoff(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data)
{
	uint8_t OnOff;
	emberAfAppPrintln("[tsl report:Gloabl] OnOff~~~~~~~~~");
	if(dataType == ZCL_BOOLEAN_ATTRIBUTE_TYPE){
		if(len==1){
			OnOff = data[0];
			if(OnOff==0 || OnOff==1){
				kk_tsl_report(eui64,EP,OnOff,clusterId,attributeId);
				return tsl_rpt_success;
			}
			return tsl_rpt_invaild_val;
		}
		return tsl_rpt_invaild_len;
	}
	return tsl_rpt_invaild_type;
}

int kk_tsl_report_windowCovering_mode(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data)
{
	uint8_t mode;
	emberAfAppPrintln("[tsl report:Window Covering] 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_tsl_report(eui64,EP,mode,clusterId,attributeId);
			return tsl_rpt_success;
		}
		return tsl_rpt_invaild_len;
	}
	return tsl_rpt_invaild_type;
}
int kk_tsl_report_windowCovering_position(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data)
{
	uint8_t position;
	emberAfAppPrintln("[tsl report:Window Covering] Position~~~~~~~~~");

	if(dataType == ZCL_INT8U_ATTRIBUTE_TYPE){
		if(len==1){
			position = data[0];
			kk_tsl_report(eui64,EP,position,clusterId,attributeId);
			return tsl_rpt_success;
		}
		return tsl_rpt_invaild_len;
	}
	return tsl_rpt_invaild_type;
}


	

int kk_tsl_report_metering_summationDelivered(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data)
{
	uint64_t summation;
	emberAfAppPrintln("[tsl report:meter(Smart Energy)] Summation Delivered~~~~~~~~~");

	if(dataType == ZCL_INT48U_ATTRIBUTE_TYPE){
		if(len==6){
			summation = KK_GET_U48(data);
			kk_tsl_report(eui64,EP,summation,clusterId,attributeId);
			return tsl_rpt_success;
		}
		return tsl_rpt_invaild_len;
	}
	return tsl_rpt_invaild_type;
}

int kk_tsl_report_ias_zoneStatus(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data)
{
	uint64_t Status;
	emberAfAppPrintln("[tsl report:IAS] Zone Status~~~~~~~~~");

	if(dataType == ZCL_BITMAP16_ATTRIBUTE_TYPE){
		if(len==2){
			Status = KK_GET_U16(data);
			kk_tsl_report(eui64,EP,Status,clusterId,attributeId);
			return tsl_rpt_success;
		}
		return tsl_rpt_invaild_len;
	}
	return tsl_rpt_invaild_type;
}



int kk_tsl_report_global_Level(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data)
{
	uint8_t level;
	emberAfAppPrintln("[tsl report:Gloabl] Level~~~~~~~~~");
	if(dataType == ZCL_INT8U_ATTRIBUTE_TYPE){
		if(len==1){
			level = data[0];
			kk_tsl_report(eui64,EP,level,clusterId,attributeId);
			return tsl_rpt_success;
			
		}
		return tsl_rpt_invaild_len;
	}
	return tsl_rpt_invaild_type;
}


int kk_tsl_report_temperature_measure(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data)
{
	int16_t Value;
	emberAfAppPrintln("[tsl report:temperature measurement] Measure Value~~~~~~~~~");
	if(dataType == ZCL_INT16S_ATTRIBUTE_TYPE){
		if(len==1){
			Value = KK_GET_U16(data);
			kk_tsl_report(eui64,EP,Value,clusterId,attributeId);
			return tsl_rpt_success;
			
		}
		return tsl_rpt_invaild_len;
	}
	return tsl_rpt_invaild_type;
}

int kk_tsl_report_illuminance_measure(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data)
{
	uint16_t Value;
	emberAfAppPrintln("[tsl report:illuminance measurement] Measure Value~~~~~~~~~");
	if(dataType == ZCL_INT16U_ATTRIBUTE_TYPE){
		if(len==1){
			Value = KK_GET_U16(data);
			kk_tsl_report(eui64,EP,Value,clusterId,attributeId);
			return tsl_rpt_success;
			
		}
		return tsl_rpt_invaild_len;
	}
	return tsl_rpt_invaild_type;
}

int kk_tsl_report_local_temperature(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data)
{
	int16_t Value;
	emberAfAppPrintln("[tsl report:local temperature] Value~~~~~~~~~");
	if(dataType == ZCL_INT16S_ATTRIBUTE_TYPE){
		if(len==1){
			Value = KK_GET_U16(data);
			kk_tsl_report(eui64,EP,Value,clusterId,attributeId);
			return tsl_rpt_success;
			
		}
		return tsl_rpt_invaild_len;
	}
	return tsl_rpt_invaild_type;
}

int kk_tsl_report_OccupiedHeatingSetpoint(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data)
{
	int16_t Value;
	emberAfAppPrintln("[tsl report:Occupied Heating Setpoint] Value~~~~~~~~~");
	if(dataType == ZCL_INT16S_ATTRIBUTE_TYPE){
		if(len==1){
			Value = KK_GET_U16(data);
			kk_tsl_report(eui64,EP,Value,clusterId,attributeId);
			return tsl_rpt_success;
			
		}
		return tsl_rpt_invaild_len;
	}
	return tsl_rpt_invaild_type;
}

int kk_tsl_report_Concentration(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data)
{
	int32_t Value;
	emberAfAppPrintln("[tsl report:Formaldehyde] Value~~~~~~~~~");
	if(dataType == ZCL_FLOAT_SINGLE_ATTRIBUTE_TYPE){
		if(len==1){
			Value = KK_GET_U32(data);
			kk_tsl_report(eui64,EP,Value,clusterId,attributeId);
			return tsl_rpt_success;
			
		}
		return tsl_rpt_invaild_len;
	}
	return tsl_rpt_invaild_type;
}




int kk_tsl_report_Formaldehyde(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data)
{
	emberAfAppPrintln("[tsl report:Formaldehyde] Value~~~~~~~~~");

	return kk_tsl_report_Concentration(eui64,EP,clusterId,attributeId,dataType,len,data);
}
int kk_tsl_report_PM2_5(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data)
{
	emberAfAppPrintln("[tsl report:PM2.5] Value~~~~~~~~~");

	return kk_tsl_report_Concentration(eui64,EP,clusterId,attributeId,dataType,len,data);
}
int kk_tsl_report_CO2(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data)
{
	emberAfAppPrintln("[tsl report:CO2] Value~~~~~~~~~");

	return kk_tsl_report_Concentration(eui64,EP,clusterId,attributeId,dataType,len,data);
}


int kk_tsl_report_colorControl_Brightness(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data)
{
	uint8_t value = data[0];
	kk_device_table_s *dev;
	UTIL_LOG_INFO("[tsl report:kk_tsl_report_global_Brightness] value:%d\n",value);

	dev = kk_device_find_by_mac(eui64);	
	if(dev == NULL){
		return tsl_rpt_err;
	}

	if(dataType == ZCL_INT8U_ATTRIBUTE_TYPE){

		if(len==1){
			dev->manage.dev.ColorLighting.color.HSL.L = value;
			dev->manage.dev.ColorLighting.color.HSL.HSL_flag |= BIT(2);
			dev->manage.dev.ColorLighting.time = halCommonGetInt32uMillisecondTick();
			emberAfCorePrintln("HSL.L = %d",dev->manage.dev.ColorLighting.color.HSL.L);

			kk_tsl_report(eui64,EP,value,clusterId,attributeId);
			return tsl_rpt_success;
		}
		return tsl_rpt_invaild_len;
	}
	return tsl_rpt_invaild_type;
}







int kk_tsl_report_colorControl_RGB(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data)
{
	uint8_t value = data[0];
	kk_device_table_s *dev;
	kk_dev_config_map *dev_info = NULL;
	kk_dev_config_item *item = NULL;	
	cJSON *root;
	int rev = 0;
	int startIdx = 0;
	cJSON* root_color = NULL;
	char tmp_Identity[64] = {0};
	COLOR_RGB g_rgb = {0,0,0};
	
	UTIL_LOG_INFO("[tsl report:kk_tsl_report_global_RGB] value:%d\n",value);

	dev = kk_device_find_by_mac(eui64);	
	if(dev == NULL){
		return tsl_rpt_err;
	}
		
	if(dataType == ZCL_INT8U_ATTRIBUTE_TYPE){
		if(attributeId == 0x0001){
			dev->manage.dev.ColorLighting.color.HSL.S = value * 100 / 254 ;
			dev->manage.dev.ColorLighting.color.HSL.HSL_flag |= BIT(1);
			dev->manage.dev.ColorLighting.time = halCommonGetInt32uMillisecondTick();
			emberAfCorePrintln("HSL.S = %d",dev->manage.dev.ColorLighting.color.HSL.S);
		}
		else if(attributeId == 0x0000){
			dev->manage.dev.ColorLighting.color.HSL.H = value * 360 / 254 ;
			dev->manage.dev.ColorLighting.color.HSL.HSL_flag |= BIT(0);
			dev->manage.dev.ColorLighting.time = halCommonGetInt32uMillisecondTick();
			emberAfCorePrintln("HSL.H = %d",dev->manage.dev.ColorLighting.color.HSL.H);
		}
	}
	return tsl_rpt_err;
}





int kk_tsl_report_iasZoneStatus(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data)
{
	uint16_t value;
	kk_device_table_s *dev;

	UTIL_LOG_INFO("[tsl report:kk_tsl_report_iasZoneStatus] value:%d\n",value);

	dev = kk_device_find_by_mac(eui64);	
	if(dev == NULL){
		return tsl_rpt_err;
	}
		
	if(dataType == ZCL_BITMAP16_ATTRIBUTE_TYPE){
		if(len==2){
			value = KK_GET_U16(data);
			kk_tsl_report(eui64,EP,value,clusterId,attributeId);
			return tsl_rpt_success;
			
		}
	}
	return tsl_rpt_err;
}
int kk_tsl_report_battery(EmberEUI64 eui64,uint8_t EP,EmberAfClusterId clusterId,EmberAfAttributeId attributeId,uint8_t dataType,uint8_t len,uint8_t *data)
{
	uint8_t value = data[0];
	kk_device_table_s *dev;
	
	UTIL_LOG_INFO("[tsl report:kk_tsl_report_battery] value:%d\n",value);

	dev = kk_device_find_by_mac(eui64);	
	if(dev == NULL){
		return tsl_rpt_err;
	}
		
	if(dataType == ZCL_INT8U_ATTRIBUTE_TYPE){
		if(len==1){
			kk_tsl_report(eui64,EP,value,clusterId,attributeId);
			return tsl_rpt_success;
		}
	}
	return tsl_rpt_err;
}




