#include "user.h"
#include "../sampleLight.h"
#include "general/ikk-token.h"
#include "app_driver/general/ikk-opt-tunnel.h"
#include "app_driver/general/ikk-cluster.h"
#define LED1	GPIO_PB1
#define LED2	GPIO_PA2

#define KEY1	GPIO_PD6
#define KEY2	GPIO_PD5

#define SYS_BUTTON_LONG_PRESS_TIME_MS			(5 * 1000)
#define DELAY_REPORT_DATA_AFTER_NWK_JOINED_MS	(3 * 1000)

#define HEART_RAND_MIN_NUM						(240 * 1000)
#define HEART_RAND_MAX_NUM						(300 * 1000)

#define LED_SLOW_BLINK_ON_TIME_MS				500
#define LED_SLOW_BLINK_OFF_TIME_MS				500
#define LED_FAST_BLINK_ON_TIME_MS				200
#define LED_FAST_BLINK_OFF_TIME_MS				200

#define LED_SLOW_BLINK_CONTINUE_TIME_MS			(60 * 1000)
#define LED_FAST_BLINK_CONTINUE_TIME_MS			(5 * 1000)

#define MIN_JOINED_NWK_DELAY_TIME_MS 			(7 * 1000) //重新上电后最短时间，用于判断是否随机延时10~40S上报心跳和CMEI和ISN

#define RAND_MIN_NUM							(3 * 1000) //最小随机数,单位MS
#define RAND_MAX_NUM 							(6 * 1000) //最大随机数

//join nwk timeout
#define NWK_STEERING_TIMEOUT_MS 				(60 * 1000)

#define HEART_DEBUG 							0
#if HEART_DEBUG
#define HEARTBEAT_TIME_MS						(20 * 1000)
#else
#define HEARTBEAT_TIME_MS						kGetRandNum(HEART_RAND_MIN_NUM, HEART_RAND_MAX_NUM)
#endif

typedef enum {KEY_SYS_ID = 1,KEY1_ID, KEY2_ID, KEY3_ID, KEY4_ID , RADAR_ID}KEY_ID_ENUM;
typedef enum {LED_RADAR_ID = 1,LED1_ID, LED2_ID, LED3_ID, LED4_ID, LED_ALL_ID}LED_ID_ENUM;
typedef enum {RELAY_CHANNEL1_ID=1, RELAY_CHANNEL2_ID, RELAY_CHANNEL3_ID, RELAY_CHANNEL4_ID, RELAY_ALL_ID}RELAY_ID_ENUM;


// BUTTONs CONFIG
BtnConfSt g_btnConfList[] = {
	{KEY_SYS_ID, KEY1, EBP_LOW, false, true, SYS_BUTTON_LONG_PRESS_TIME_MS},	// Key1
	{KEY1_ID, KEY2, EBP_LOW, false, true, SYS_BUTTON_LONG_PRESS_TIME_MS},	// Key2
};
// LEDs CONFIG
LedConfSt g_ledConfList[] = {
	{(uint8_t)LED1_ID, 1, {LED1, PWM_UNKNOW_ID, PIN_UNKNOW, PWM_UNKNOW_ID, PIN_UNKNOW, PWM_UNKNOW_ID, PIN_UNKNOW, PWM_UNKNOW_ID}, ELP_HIGH },
	{(uint8_t)LED2_ID, 1, {LED2, PWM_UNKNOW_ID, PIN_UNKNOW, PWM_UNKNOW_ID, PIN_UNKNOW, PWM_UNKNOW_ID, PIN_UNKNOW, PWM_UNKNOW_ID}, ELP_HIGH },
	{(uint8_t)LED_ALL_ID, 2, {LED1, PWM_UNKNOW_ID, LED2, PWM_UNKNOW_ID, PIN_UNKNOW, PWM_UNKNOW_ID, PIN_UNKNOW, PWM_UNKNOW_ID}, ELP_HIGH }
};

BindObjSt cluster_obj_list[] = {
	{ZCL_CLUSTER_GEN_ON_OFF, ZCL_ATTRID_ONOFF,  1},
};

uint32_t u32PeroidIntervalMS   = 2*1000;

void JoinCompleteCallback(NwkJoinCompltEnum nwkcomplt );
void kUserNetworkStatusNotify(NwkStatusEnum nwkst );
void kUserNetworkExitCompleteCallback(void);
void kUserOnOffClusterOnOffStatusCallback(uint8_t endpoint, OnOffStatusEnum estatus );;
kk_err_t kUserOODMessageIncoming(uint8_t channel, uint8_t opcode, uint8_t args_in_out[], uint8_t *length_in_out );

void kUserButtonAcitonCallback(unsigned char button_id, BtnActionEnum action );
void kUserLedActionDoneCallback(unsigned char id);
void Test(void );

void App_Init(void)
{
	iKonkeAfSelfPrint("\r\n************************************************\r\n");
	iKonkeAfSelfPrint("\r\n****************APP   Init***********************\r\n");
//	iKonkeAfSelfPrint("xxx Reboot Reason: R-INFO(0x%x: %p), R-EXTEND(0x%x: %p) xxx\r\n"
//		, halGetResetInfo(), halGetResetString()
//		, halGetExtendedResetInfo(), halGetExtendedResetString());
//	iKonkeAfSelfPrint("xxx Network Status: %d, systime: %d xxx\r\n", emberAfNetworkState()
//		, halCommonGetInt32uMillisecondTick());
	iKonkeAfSelfPrint("\r\n************************************************\r\n");
	#if 1
	kk_err_t err = kBtnModuleInit(g_btnConfList, sizeof(g_btnConfList) / sizeof(BtnConfSt), kUserButtonAcitonCallback);
		if( err != KET_OK ) {
			iKonkeAfSelfPrint("Err: Button Module Init failed(%d)!!\r\n", err);
		}
	#endif
	#if 0
		err = kPwmModuleInit(g_pwmConfList, sizeof(g_pwmConfList)/sizeof(PwmConfSt), kUserPwmActionDoneCallback);
		if( err != KET_OK ) {
			iKonkeAfSelfPrint("Err: PWM Module Init failed(%d)!!\r\n", err);
		}
	#endif
		err = kLedModuleInit(g_ledConfList, sizeof(g_ledConfList) / sizeof(LedConfSt), kUserLedActionDoneCallback);
		if( err != KET_OK ) {
			iKonkeAfSelfPrint("Err: Led Module Init failed(%d)!!\r\n", err);
		}

		kNwkModuleInit(cluster_obj_list,sizeof(cluster_obj_list) / sizeof(cluster_obj_list[0]), kUserNetworkStatusNotify, kUserNetworkExitCompleteCallback);
		err =  kNwkScheduleTaskRegister(HEARTBEAT_TIME_MS);
		if( err != KET_OK ) {
			iKonkeAfSelfPrint("Err: HeatBeat Task Register Failed!!\r\n", err);
		}
		// init the private cluster protocol module.
		err =  kOptTunnelModuleInit(kUserOODMessageIncoming);
		if( err != KET_OK ) {
			iKonkeAfSelfPrint("Err: kUserOODMessageIncoming Register Failed(%d)!!\r\n", err);
		}
		// ZCL
		kZclOnOffClusterServerInit(kUserOnOffClusterOnOffStatusCallback);

		//重写attribute
		//Update_Local_Attribute_Info();
		Test();

}
void Test(void )
{
	iKonkeAfSelfPrint("###### Test,random = (%d),%d!!\r\n",zb_random(), kGetRandNum(HEART_RAND_MIN_NUM, HEART_RAND_MAX_NUM));



}
s32 kUserScheduleTaskHandler(void *arg)
{
	iKonkeAfSelfPrint("##########kUserScheduleTaskHandlerCallback!!\r\n");
	kOptTunnelCommonReport(ECA_OPTDATA);
	return 0;
}
void JoinCompleteCallback(NwkJoinCompltEnum nwkcomplt )
{
	iKonkeAfSelfPrint("#########JoinCompleteCallback = %d\r\n", nwkcomplt);
	switch(nwkcomplt) {
		case (EJC_JOIN_FAILED ):
		{
			//kLedOptTrigger(1, 100, 100,  6, LED_ON, LED_OFF);
			LED_OPT_OFF(LED2_ID);
			kUserNetworkExitCompleteCallback();
			break;
		}
		case (EJC_JOIN_SUCCEED):
		{

			break;
		}
		default: break;
	}
}
void kUserNetworkStatusNotify(NwkStatusEnum nwkst )
{
	iKonkeAfSelfPrint("#############################kUserNetworkStatusNotify = %d\r\n", nwkst);
	switch(nwkst) {
		case (ENS_ONLINE ):
		{
			uint32_t randTimeMS = DELAY_REPORT_DATA_AFTER_NWK_JOINED_MS;
			//power on after joined network
			uint32_t currentTimeMS = clock_time();
			if ( currentTimeMS < MIN_JOINED_NWK_DELAY_TIME_MS){
				randTimeMS = kGetRandNum(RAND_MIN_NUM, RAND_MAX_NUM);
			}else {
				//不是重新上电或复位，蓝色闪烁需关闭
				//kLedOptTrigger(LED_ALL_ID, 0, 0, 0, LED_OFF, LED_IGNORE);
			}
			LED_OPT_ON(LED2_ID);
			kUserScheduleTaskHandler(0);
			iKonkeAfSelfPrint("Joined Network RandTime(%dms) CurrentTime(%ld)\r\n", randTimeMS, currentTimeMS);
			break;
		}
		case (ENS_JOINING):
		{
			kLedOptTrigger((uint8_t)LED2_ID, LED_SLOW_BLINK_ON_TIME_MS, LED_SLOW_BLINK_OFF_TIME_MS \
					,LED_SLOW_BLINK_CONTINUE_TIME_MS/(LED_SLOW_BLINK_ON_TIME_MS+LED_SLOW_BLINK_OFF_TIME_MS), LED_ON, LED_IGNORE);
			break;
		}
		case (ENS_LEAVED):
		{
			iKonkeAfSelfPrint("#####Enter Leave\r\n");
			kLedOptTrigger((uint8_t)LED2_ID, LED_FAST_BLINK_ON_TIME_MS, LED_FAST_BLINK_OFF_TIME_MS \
						,LED_FAST_BLINK_CONTINUE_TIME_MS/(LED_FAST_BLINK_ON_TIME_MS+LED_FAST_BLINK_ON_TIME_MS), LED_ON, LED_IGNORE);
			//关闭勿扰模式
			//kSetIndicatorNotDisturbModeFlg(false);

			break;
		}
		default:
		{
			break;
		}
	}
}
//on off 属性改变后的回调函数，一般用来操作继电器，过零检测，如果没有过零检测可以在这里同步LED状态
void kUserOnOffClusterOnOffStatusCallback(uint8_t endpoint, OnOffStatusEnum estatus )
{
	iKonkeAfSelfPrint("OnOff-status: endpoint(%d), estatus(%d)\r\n", endpoint, estatus);

	switch(endpoint) {
		case (1):
		{
			if(estatus == EOOS_OFF)
				LED_OPT_OFF(LED1_ID);
			else
				LED_OPT_ON(LED1_ID);
			break;
		}
		default: break;
	}
}
void kUserButtonAcitonCallback(unsigned char button_id, BtnActionEnum action )
{
	iKonkeAfSelfPrint("kUserButton: ButtonId(%d), Action(%d)\r\n", button_id, action);
	switch(button_id)
	{
		case KEY_SYS_ID:												//sys botton
		{
			switch(action)
			{
				case EBA_CLICK:
				{
					if(kNwkGetCurrentStatus() == ENS_ONLINE)
						kLedOptTrigger(LED2_ID,200,200,1,LED_OFF,LED_IGNORE);			//绿灯闪烁一次
					else if(kNwkGetCurrentStatus() == ENS_LEAVED)
					{
						kNwkFactoryReset(false);
						kNwkJoiningStart(NWK_STEERING_TIMEOUT_MS,JoinCompleteCallback);						//开启组网
					}
				}
					break;
				case EBA_LONGPRESS:
				{
					kNwkFactoryReset(true);
					iKonkeAfSelfPrint("Start Leave...........\r\n");
				}
					break;
				default:
					break;
			}
			break;
		}
		case KEY1_ID:
		{
			switch(action)
			{
				case EBA_CLICK:
				{
					zcl_onOffAttr_t *pOnOff = zcl_onoffAttrGet();
					iKonkeAfSelfPrint("Get onoff (%d),%d\r\n", pOnOff->onOff, pOnOff->startUpOnOff);
					ON_OFF_Cmd_Handler(1,ZCL_CMD_ONOFF_TOGGLE);
				}
					break;
				case EBA_LONGPRESS:
					break;
				default:
					break;
			}
			break;
		}
		default:
			break;
	}
}
bool kZclClusterReportChangeCallback(uint8_t endpoint, uint16_t clusterId, uint16_t attributeId)
{

	return true;
}
//ota升级失败或入网成功和失败后LED闪烁完成后处理，需要根据不同产品来修改
static void kSetLedStatus(LED_ID_ENUM id)
{
	if(kNwkGetCurrentStatus() == ENS_LEAVED){
		LED_OPT_OFF(LED2_ID);
	}
	else{
		LED_OPT_ON(LED2_ID);
	}
}
//LED闪烁完成，可以用来恢复继电器的LED状态
void kUserLedActionDoneCallback(unsigned char id)
{
	iKonkeAfSelfPrint("##############kUserLedActionDoneCallback id(%d)nwk(%d)##################\r\n", id,kNwkGetCurrentStatus());
	kSetLedStatus(id);
}
kk_err_t kUserOODMessageIncoming(uint8_t channel, uint8_t opcode, uint8_t args_in_out[], uint8_t *length_in_out )
{
	if( NULL == args_in_out || NULL == length_in_out ) {
		return KET_ERR_INVALID_POINTER;
	}

	iKonkeAfSelfPrint("OOD-INCOMING: channel(%d), opcode(%x)--\r\n", channel, opcode);
	for(int index = 0; index < *length_in_out; ++index ) {
		iKonkeAfSelfPrint("%x ", args_in_out[index]);
	}
	iKonkeAfSelfPrint("--------------------------------------\r\n");

	switch(opcode) {
		case (0x00): // get the device snap.
		{
			args_in_out[0] = 0x00;
			args_in_out[1] = 0;

			iKonkeAfSelfPrint("OOOOOOPCODE: 1(%d), 2(%d), \r\n", args_in_out[1], args_in_out[2]);
			*length_in_out = 2;
			break;
		}
		case (0xFF):
		{
			uint8_t permitJoinTimeS = args_in_out[0]; //unit:s
			iKonkeAfSelfPrint("###Opcode is channel(%d) JoinPermitTime(0x%X)!!\r\n",channel,  permitJoinTimeS);
			//路由协同组网,黄灯闪烁(OTA升级)时不协同组网闪灯
			if (kLedIsBlinking(LED2_ID) != true
					&& permitJoinTimeS != 0
					&& kNwkGetCurrentStatus() != ENS_JOINING){
				iKonkeAfSelfPrint("####LED Blink\r\n");
				kLedOptTrigger(LED2_ID,  LED_SLOW_BLINK_ON_TIME_MS, LED_SLOW_BLINK_OFF_TIME_MS,
						permitJoinTimeS * 1000/(LED_SLOW_BLINK_ON_TIME_MS+LED_SLOW_BLINK_OFF_TIME_MS), LED_ON, LED_OFF);
			}else if (kLedIsBlinking(LED2_ID) == true
					&& permitJoinTimeS == 0
					&& kNwkGetCurrentStatus() != ENS_JOINING){
				kLedOptTrigger(LED2_ID, 0, 0, 0, LED_OFF, LED_IGNORE);
//				kLEDOffAction(LED_ALL_ID);
				kSetLedStatus(LED2_ID);
			}
			return KET_NO_RESPONSE;
		}

		default: {
			iKonkeAfSelfPrint("Err: opcode is not exist(%d:%X)!!\r\n", channel, opcode);
			args_in_out[0] = ERR_NO_OPCODE;
			*length_in_out = 1;
			break;
		}
	}

	return KET_OK;
}


//退网5S快闪结束后的回调函数，一般用于面板、插座和窗帘面板退网完成后在全部关闭时复位
void kUserNetworkExitCompleteCallback(void)
{
	iKonkeAfSelfPrint("##############kUserNetworkExitCompleteCallback(%d)##################\r\n");
//	zcl_onOffAttr_t *pOnOff = zcl_onoffAttrGet();
//	bool bIsAllOffFlg = true;
//	for (uint8_t i = 1; i <= 1; i++){
//		if (pOnOff->onOff){
//			bIsAllOffFlg = false;
//			break;
//		}
//	}
//	if (bIsAllOffFlg == true){
		SYSTEM_RESET();
//	}
}
