/********************************************************************************************************
 * @file	zcl_onOffCb.c
 *
 * @brief	This is the source file for zcl_onOffCb
 *
 * @author	Zigbee Group
 * @date	2019
 *
 * @par     Copyright (c) 2019, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
 *          All rights reserved.
 *
 *          Redistribution and use in source and binary forms, with or without
 *          modification, are permitted provided that the following conditions are met:
 *
 *              1. Redistributions of source code must retain the above copyright
 *              notice, this list of conditions and the following disclaimer.
 *
 *              2. Unless for usage inside a TELINK integrated circuit, redistributions
 *              in binary form must reproduce the above copyright notice, this list of
 *              conditions and the following disclaimer in the documentation and/or other
 *              materials provided with the distribution.
 *
 *              3. Neither the name of TELINK, nor the names of its contributors may be
 *              used to endorse or promote products derived from this software without
 *              specific prior written permission.
 *
 *              4. This software, with or without modification, must only be used with a
 *              TELINK integrated circuit. All other usages are subject to written permission
 *              from TELINK and different commercial license may apply.
 *
 *              5. Licensee shall be solely responsible for any claim to the extent arising out of or
 *              relating to such deletion(s), modification(s) or alteration(s).
 *
 *          THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 *          ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 *          WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *          DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY
 *          DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *          (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *          LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *          ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *          (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *          SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *******************************************************************************************************/
#if (__PROJECT_3LIGHT_PANEL_DEMO__)

/**********************************************************************
 * INCLUDES
 */
#include "tl_common.h"
#include "zb_api.h"
#include "zcl_include.h"
#include PROJECT_H
#include "zcl.h"
/**********************************************************************
 * LOCAL CONSTANTS
 */
#define ZCL_ONOFF_TIMER_INTERVAL		100    //the timer interval to change the offWaitTime/onTime attribute of the ONOFF cluster

/**********************************************************************
 * LOCAL VARIABLES
 */
static ev_timer_event_t *onWithTimedOffTimerEvt = NULL;

/**********************************************************************
 * FUNCTIONS
 */

/*********************************************************************
 * @fn      sampleLight_onOffInit
 *
 * @brief
 *
 * @param   None
 *
 * @return  None
 */
void sampleLight_onOffInit(void)
{
//	zcl_onOffAttr_t *pOnOff = zcl_onoffAttrGet();
//
//	sampleLight_onoff(pOnOff->onOff);
}
/*********************************************************************
 * @fn      sampleLight_updateOnOff
 *
 * @brief
 *
 * @param   None
 *
 * @return  None
 */
void sampleLight_updateOnOff(void)
{
//	zcl_onOffAttr_t *pOnOff = zcl_onoffAttrGet();
//
//	hwLight_onOffUpdate(pOnOff->onOff);
}

/*********************************************************************
 * @fn      sampleLight_onoff
 *
 * @brief
 *
 * @param   ZCL_CMD_ONOFF_ON / ZCL_ONOFF_STATUS_OFF
 *
 * @return  None
 */
void sampleLight_onoff(u8 cmd)
{
//	zcl_onOffAttr_t *pOnOff = zcl_onoffAttrGet();
//
//	if(cmd == ZCL_CMD_ONOFF_ON){
//		pOnOff->globalSceneControl = TRUE;
//
//		pOnOff->onOff = ZCL_ONOFF_STATUS_ON;
//		if(pOnOff->onTime == 0){
//			pOnOff->offWaitTime = 0;
//		}
//	}else if(cmd == ZCL_CMD_ONOFF_OFF){
//		pOnOff->onOff = ZCL_ONOFF_STATUS_OFF;
//		pOnOff->onTime = 0;
//	}else{
//		if(pOnOff->onOff == ZCL_ONOFF_STATUS_OFF){
//			pOnOff->globalSceneControl = TRUE;
//
//			pOnOff->onOff = ZCL_ONOFF_STATUS_ON;
//			if(pOnOff->onTime == 0){
//				pOnOff->offWaitTime = 0;
//			}
//		}else{
//			pOnOff->onOff = ZCL_ONOFF_STATUS_OFF;
//			pOnOff->onTime = 0;
//		}
//	}

	//light_fresh();

#ifdef ZCL_SCENE
//	zcl_sceneAttr_t *pScene = zcl_sceneAttrGet();
//	pScene->sceneValid = 0;
#endif
}

/*********************************************************************
 * @fn      sampleLight_OnWithTimedOffTimerCb
 *
 * @brief   timer event to process the ON_WITH_TIMED_OFF command
 *
 * @param   arg
 *
 * @return  0: timer continue on; -1: timer will be canceled
 */
static s32 sampleLight_OnWithTimedOffTimerCb(void *arg)
{
//	zcl_onOffAttr_t *pOnOff = zcl_onoffAttrGet();
//
//	if((pOnOff->onOff == ZCL_ONOFF_STATUS_ON) && pOnOff->onTime){
//		pOnOff->onTime--;
//		if(pOnOff->onTime <= 0){
//			pOnOff->offWaitTime = 0;
//			sampleLight_onoff(ZCL_CMD_ONOFF_OFF);
//		}
//	}
//
//	if((pOnOff->onOff == ZCL_ONOFF_STATUS_OFF) && pOnOff->offWaitTime){
//		pOnOff->offWaitTime--;
//		if(pOnOff->offWaitTime <= 0){
//			onWithTimedOffTimerEvt = NULL;
//			return -1;
//		}
//	}
//
//	if(pOnOff->onTime || pOnOff->offWaitTime){
//		return 0;
//	}else{
//		onWithTimedOffTimerEvt = NULL;
//		return -1;
//	}
}

/*********************************************************************
 * @fn      sampleLight_OnWithTimedOffTimerStop
 *
 * @brief   force to stop the OnWithTimedOff timer
 *
 * @param
 *
 * @return
 */
static void sampleLight_OnWithTimedOffTimerStop(void)
{
	if(onWithTimedOffTimerEvt){
		TL_ZB_TIMER_CANCEL(&onWithTimedOffTimerEvt);
	}
}

/*********************************************************************
 * @fn      sampleLight_onoff_onWithTimedOffProcess
 *
 * @brief
 *
 * @param   cmd
 *
 * @return  None
 */
static void sampleLight_onoff_onWithTimedOffProcess(uint8_t ep,zcl_onoff_onWithTimeOffCmd_t *cmd)
{
	zcl_onOffAttr_t *pOnOff = zcl_onoffAttrGet(ep);

	if(cmd->onOffCtrl.bits.acceptOnlyWhenOn && (pOnOff->onOff == ZCL_ONOFF_STATUS_OFF)){
		return;
	}

	if(pOnOff->offWaitTime && (pOnOff->onOff == ZCL_ONOFF_STATUS_OFF)){
		pOnOff->offWaitTime = min2(pOnOff->offWaitTime, cmd->offWaitTime);
	}else{
		pOnOff->onTime = max2(pOnOff->onTime, cmd->onTime);
		pOnOff->offWaitTime = cmd->offWaitTime;
		sampleLight_onoff(ZCL_CMD_ONOFF_ON);
	}

	if((pOnOff->onTime < 0xFFFF) && (pOnOff->offWaitTime < 0xFFFF)){
		if(pOnOff->onTime || pOnOff->offWaitTime){
			sampleLight_OnWithTimedOffTimerStop();
			onWithTimedOffTimerEvt = TL_ZB_TIMER_SCHEDULE(sampleLight_OnWithTimedOffTimerCb, NULL, ZCL_ONOFF_TIMER_INTERVAL);
		}
	}
}

/*********************************************************************
 * @fn      sampleLight_onoff_offWithEffectProcess
 *
 * @brief
 *
 * @param   cmd
 *
 * @return  None
 */
static void sampleLight_onoff_offWithEffectProcess(uint8_t ep,zcl_onoff_offWithEffectCmd_t *cmd)
{
	//TODO: FIXED ME

	sampleLight_onoff(ZCL_CMD_ONOFF_OFF);
}

/*********************************************************************
 * @fn      sampleLight_onoff_onWithRecallGlobalSceneProcess
 *
 * @brief
 *
 * @param   cmd
 *
 * @return  None
 */
static void sampleLight_onoff_onWithRecallGlobalSceneProcess(void)
{

}


extern void ON_OFF_Cmd_Handler(uint8_t endpoint,bool onoff);
void zclReportCmdHandler(uint8_t ep,uint16_t cluster,zclReportCmd_t *reportInfo)
{
	//iKonkeAfSelfPrint("######sampleLight_zclReportCmd,attr = %d,data type=%d,data = %d\r\n",reportInfo->attrList[0].attrID,reportInfo->attrList[0].dataType,reportInfo->attrList[0].attrData[0]);

	switch(cluster)
	{
		case ZCL_CLUSTER_GEN_ON_OFF:
		{
			for(uint8_t i = 0;i<(reportInfo->numAttr);i++)
			{
				if(reportInfo->attrList[i].attrID == ZCL_ATTRID_ONOFF)
				{
					bool on_off_ctr = reportInfo->attrList[0].attrData[i];
					ON_OFF_Cmd_Handler(ep,on_off_ctr);
				}
			}


			break;
		}
		default:
			break;
	}




}

status_t sampleLight_onOffCb(zclIncomingAddrInfo_t *pAddrInfo, u8 cmdId, void *cmdPayload)
{
	uint8_t ep  = pAddrInfo->dstEp;
	zcl_onOffAttr_t *pOnOff = zcl_onoffAttrGet(ep);
	bool on_off_ctr;
	switch(cmdId){
		case ZCL_CMD_ONOFF_ON:
		{
			pOnOff->globalSceneControl = TRUE;
			pOnOff->onOff = ZCL_ONOFF_STATUS_ON;
			on_off_ctr = true;
			if(pOnOff->onTime == 0){
				pOnOff->offWaitTime = 0;
			}
			ON_OFF_Cmd_Handler(ep,on_off_ctr);
			break;
		}
		case ZCL_CMD_ONOFF_OFF:
		{
			pOnOff->onOff = ZCL_ONOFF_STATUS_OFF;
			pOnOff->onTime = 0;
			on_off_ctr = false;
			ON_OFF_Cmd_Handler(ep,on_off_ctr);
			break;
		}
		case ZCL_CMD_ONOFF_TOGGLE:
		{
			if(pOnOff->onOff == ZCL_ONOFF_STATUS_OFF){
				pOnOff->globalSceneControl = TRUE;

				pOnOff->onOff = ZCL_ONOFF_STATUS_ON;
				on_off_ctr = true;
				if(pOnOff->onTime == 0){
					pOnOff->offWaitTime = 0;
				}
			}else{
				pOnOff->onOff = ZCL_ONOFF_STATUS_OFF;
				pOnOff->onTime = 0;
				on_off_ctr = false;
			}

			ON_OFF_Cmd_Handler(ep,on_off_ctr);
			break;
		}
		case ZCL_CMD_OFF_WITH_EFFECT:
			if(pOnOff->globalSceneControl == TRUE){
				/* TODO: store its settings in its global scene */

				pOnOff->globalSceneControl = FALSE;
			}
			sampleLight_onoff_offWithEffectProcess(ep,(zcl_onoff_offWithEffectCmd_t *)cmdPayload);
			break;
		case ZCL_CMD_ON_WITH_RECALL_GLOBAL_SCENE:
			if(pOnOff->globalSceneControl == FALSE){
				sampleLight_onoff_onWithRecallGlobalSceneProcess();
				pOnOff->globalSceneControl = TRUE;
			}
			break;
		case ZCL_CMD_ON_WITH_TIMED_OFF:
			sampleLight_onoff_onWithTimedOffProcess(ep,(zcl_onoff_onWithTimeOffCmd_t *)cmdPayload);
			break;
		default:
			break;
	}
	return ZCL_STA_SUCCESS;
}

#endif  /* __PROJECT_TL_DIMMABLE_LIGHT__ */
