#include "tal_memory.h"

#include "app_common.h"
#include "app_key.h"
#include "app_mfg.h"
#include "bsp.h"




// VOID_T report_send_result_cb(TAL_SEND_ST_E status, TAL_ZG_SEND_DATA_T *pdata)
// {
//   TAL_PR_TRACE("Zigbee report send SUCCESS (status: %d)", status);
//     switch (status) {
//         case SEND_ST_OK:
//             // TAL_PR_TRACE("Zigbee report send SUCCESS (ZCL ID: %d)", pdata->zcl_id);
//             break;
//         case SEND_ST_ERR:
//             TAL_PR_TRACE("Zigbee report FAILED: Network error");
//             break;
//         case SEND_ST_MEMORY_ERR:
//             TAL_PR_TRACE("Zigbee report FAILED: Memory error");
//             break;
//         case SEND_ST_QUEUE_FULL_ERR:
//             TAL_PR_TRACE("Zigbee report FAILED: Send queue full");
//             break;
//         case SEND_ST_NO_NETWORK:
//             TAL_PR_TRACE("Zigbee report FAILED: No network");
//             break;
//         case SEND_ST_ADDR_MODE_ERR:
//             TAL_PR_TRACE("Zigbee report FAILED: Address error");
//             break;
//         case SEND_ST_SEND_DOING:
//             TAL_PR_WARN("Zigbee report PENDING: Waiting to send");
//             break;
//         default:
//             TAL_PR_TRACE("Zigbee report FAILED: Unknown status = %d", status);
//             break;
//     }
// }

STATIC VOID_T report_send_result_cb(TAL_SEND_ST_E status, TAL_ZG_SEND_DATA_T *pdata)
{
    TAL_PR_TRACE("report_send_result_cb: status=%d, src_ep=%d", status, pdata ? pdata->addr.type.dev.src_ep : -1);
    // 可根据需要添加更多处理逻辑
}

/********************************************************************************
 * @brief Sends a standard on/off attribute report to the Zigbee gateway.
 * @author ysl
 * @param[in] ep_id - Endpoint ID of the device
 * @param[in] onoff - On/off status value to report (LED_ON or LED_OFF)
 * @return void
 * @date 2025.07
 *
 * This function constructs a ZCL report frame with:
 * - ZCL_ID_ONOFF as the cluster ID
 * - CMD_REPORT_ATTRIBUTES_COMMAND_ID as the command ID
 * - Sends to the gateway endpoint (0x01) from the specified source endpoint
 * - Attribute reported: ATTR_ON_OFF_ATTRIBUTE_ID (type: boolean)
 *
 * The data is sent unicast to TUYA_GATEWAY_ADDRESS using QoS_1.
 * @note Function: __report_onoff
 ********************************************************************************/
STATIC VOID_T __report_onoff(UINT8_T ep_id, LED_STATUS_E onoff)
{
  TAL_ZG_SEND_DATA_T send_data = {
      .zcl_id = ZCL_ID_ONOFF,
      .delay_time = 0,
      .random_time = 0,
      .qos = QOS_0,
      .direction = ZG_ZCL_DATA_SERVER_TO_CLIENT,
      .frame_type = ZG_ZCL_FRAME_TYPE_GLOBAL,
      .command_id = CMD_REPORT_ATTRIBUTES_COMMAND_ID,

      // unicast to gateway
      .addr.mode = SEND_MODE_DEV,
      .addr.type.dev.dst_addr = TUYA_GATEWAY_ADDRESS,
      .addr.type.dev.dst_ep = 0x01,  // gateway endpoint
      .addr.type.dev.src_ep = ep_id, // device endpoint
      .addr.type.dev.cluster_id = CLUSTER_ON_OFF_CLUSTER_ID,

      .data.zg.attr_sum = 1,
      .data.zg.attr[0].attr_id = ATTR_ON_OFF_ATTRIBUTE_ID,
      .data.zg.attr[0].type = ATTR_BOOLEAN_ATTRIBUTE_TYPE,
      .data.zg.attr[0].size = 1,
      .data.zg.attr[0].value[0] = (UINT8_T)onoff,
  };
  TAL_PR_TRACE("======================================");
  TAL_PR_TRACE("src_ep        : %d", send_data.addr.type.dev.src_ep);
  TAL_PR_TRACE("value[0]        : %d", send_data.data.zg.attr[0].value[0]);
  TAL_PR_TRACE("======================================");
    // tal_zg_clear_send_data(ZG_CLEAR_ALL_ZCL_ID, &send_data.zcl_id);
  tal_zg_send_data(&send_data, report_send_result_cb, 2000);

}

STATIC VOID_T __first_report_onoff(UINT8_T ep_id, LED_STATUS_E onoff)
{
  TAL_ZG_SEND_DATA_T send_data = {
    .zcl_id = ZCL_ID_ONOFF,
    .delay_time = 0,
    .random_time = 0,
    .qos = QOS_1,
    .direction = ZG_ZCL_DATA_SERVER_TO_CLIENT,
    .frame_type = ZG_ZCL_FRAME_TYPE_GLOBAL,
    .command_id = CMD_REPORT_ATTRIBUTES_COMMAND_ID,

    // unicast to gateway
    .addr.mode = SEND_MODE_DEV,
    .addr.type.dev.dst_addr = TUYA_GATEWAY_ADDRESS,
    .addr.type.dev.dst_ep = 0x01,                           // gateway endpoint
    .addr.type.dev.src_ep = ep_id,                          // device endpoint
    .addr.type.dev.cluster_id = CLUSTER_ON_OFF_CLUSTER_ID,

    .data.zg.attr_sum = 1,
    .data.zg.attr[0].attr_id = ATTR_ON_OFF_ATTRIBUTE_ID,
    .data.zg.attr[0].type = ATTR_BOOLEAN_ATTRIBUTE_TYPE,
    .data.zg.attr[0].size = 1,
    .data.zg.attr[0].value[0] = (UINT8_T)onoff,
  };
  TAL_PR_TRACE("--------------------------------------");
  TAL_PR_TRACE("src_ep          : %d", send_data.addr.type.dev.src_ep);
  TAL_PR_TRACE("value[0]        : %d", send_data.data.zg.attr[0].value[0]);
  TAL_PR_TRACE("--------------------------------------");
  // tal_zg_clear_send_data(ZG_CLEAR_ALL_ZCL_ID, &send_data.zcl_id);
  tal_zg_send_data(&send_data, NULL, 1000);
}

/********************************************************************************
 * @brief Sends a user-defined ZCL on/off report to the gateway.
 * @author ysl
 * @param[in] ep_id - Endpoint ID
 * @param[in] onoff - On/off value
 * @return void
 * @date 2025.07
 *
 * Uses a custom ZCL ID and command ID (0x05) for reporting.
 * Clears previous queued messages before sending.
 * @note Function: __user_report_onoff
 ********************************************************************************/
STATIC VOID_T __user_report_onoff(UINT8_T ep_id, LED_STATUS_E onoff)
{
  TAL_ZG_SEND_DATA_T send_data = {
      .zcl_id = USER_ZCL_ID,
      .delay_time = 0,
      .random_time = 0,
      .qos = QOS_1,
      .direction = ZG_ZCL_DATA_SERVER_TO_CLIENT,
      .frame_type = ZG_ZCL_FRAME_TYPE_GLOBAL,
      .command_id = 0x05,

      // unicast to gateway
      .addr.mode = SEND_MODE_DEV,
      .addr.type.dev.dst_addr = TUYA_GATEWAY_ADDRESS,
      .addr.type.dev.dst_ep = 0x01,  // gateway endpoint
      .addr.type.dev.src_ep = ep_id, // device endpoint
      .addr.type.dev.cluster_id = CLUSTER_ON_OFF_CLUSTER_ID,

      .data.zg.attr_sum = 1,
      .data.zg.attr[0].attr_id = ATTR_ON_OFF_ATTRIBUTE_ID,
      .data.zg.attr[0].type = ATTR_BOOLEAN_ATTRIBUTE_TYPE,
      .data.zg.attr[0].size = 1,
      .data.zg.attr[0].value[0] = (UINT8_T)onoff,
  };
  TAL_PR_TRACE("======================================");
  TAL_PR_TRACE("src_ep        : %d", send_data.addr.type.dev.src_ep);
  TAL_PR_TRACE("value[0]        : %d", send_data.data.zg.attr[0].value[0]);
  TAL_PR_TRACE("======================================");
  tal_zg_clear_send_data(ZG_CLEAR_ALL_ZCL_ID, &send_data.zcl_id);
  tal_zg_send_data(&send_data, NULL, 2000);
}

VOID_T app_onoff_cluster_read_report(UINT8_T ep_id)
{
    LED_STATUS_E onoff;
    // read
    tal_zg_read_attribute(ep_id, CLUSTER_ON_OFF_CLUSTER_ID, ATTR_ON_OFF_ATTRIBUTE_ID, &onoff, ATTR_BOOLEAN_ATTRIBUTE_TYPE);
    // report
    __first_report_onoff(ep_id, onoff);
}

/********************************************************************************
 * @brief Writes the on/off attribute and sends a ZCL report to the gateway.
 * @author ysl
 * @param[in] ep_id - Endpoint ID
 * @param[in] onoff - On/off value
 * @return void
 * @date 2025.07
 *
 * Writes local attribute and triggers __report_onoff for sync.
 * @note Function: app_onoff_cluster_write_report
 ********************************************************************************/
VOID_T app_onoff_cluster_write_report(UINT8_T ep_id, LED_STATUS_E onoff)
{
#if 1
  // update
  tal_zg_write_attribute(ep_id, CLUSTER_ON_OFF_CLUSTER_ID, ATTR_ON_OFF_ATTRIBUTE_ID, &onoff, ATTR_BOOLEAN_ATTRIBUTE_TYPE);
  // report
  __report_onoff(ep_id, onoff);
  // __user_report_onoff(ep_id, onoff);
#endif
}

/********************************************************************************
 * @brief Sends on/off report for each relay channel based on current status.
 * @author ysl
 * @return void
 * @date 2025.07
 *
 * Loops through all relay channels and sends status reports.
 * @note Function: all_update_data
 ********************************************************************************/
VOID_T all_update_data(VOID_T)
{
#if 0
  UINT8_T i;
  for (i = 0; i < CHANNEL_NUM; i++)
  {
    if ((device_status.relStatus & (1 << i)))
      app_onoff_cluster_write_report(i + 1, LED_ON);
    else
      app_onoff_cluster_write_report(i + 1, LED_OFF);
  }
#endif
}