/**
 * @file tuya_app_main.c
 * @author www.tuya.com
 * @brief tuya_app_main module is used to
 * @version 0.1
 * @date 2022-10-28
 *
 * @copyright Copyright (c) tuya.inc 2022
 *
 */

#include <stdlib.h>

#include "tuya_cloud_types.h"
#include "tuya_device_cfg.h"
#include "tuya_svc_netmgr.h"
#if defined(ENABLE_WIFI_SERVICE) && (ENABLE_WIFI_SERVICE == 1)
#include "tuya_iot_wifi_api.h"
#endif
#if defined(ENABLE_WIRED) && (ENABLE_WIRED == 1)
#include "tuya_iot_base_api.h"
#endif
#include "tuya_iot_com_api.h"
#include "tuya_ws_db.h"

#include "tal_system.h"
#include "tal_log.h"
#include "base_event.h"
#include "mf_test.h"
#include "mqc_app.h"
#if defined(ENABLE_LWIP) && (ENABLE_LWIP == 1)
#include "lwip_init.h"
#endif

#include "tal_uart.h"
#include "tuya_ai_toy.h"
#include "tuya_device_cfg.h"
#include "tuya_ai_battery.h"
#include "app_key.h"
#include "app_touch.h"

#include "app_a_voice.h"
#include "app_a_pir.h"


/***********************************************************
************************macro define************************
***********************************************************/

//#define PID         "e3jrgtmuqsljru1t"      // TUYA T5AI-EVB xiaozhi box
//#define PID         "zbwbmdyemfa4ipkw"      // AI-Chat Multi-Mode PID
// #define PID             "yr4ybissxrezmu2u"      // AI-Chat Demo PID
//#define PID          "pgjdljpik5b5cizn"   //xiaoya
 //#define PID         "zbwbmdyemfa4ipkw"      // AI-Chat Multi-Mode PID
#define PID             "7ybwkhuhcrigju0b"      // leo
// #define UUID        "your uuid"
// #define AUTHKEY     "your authkey"

/***********************************************************
***********************typedef define***********************
***********************************************************/


/***********************************************************
********************function declaration********************
***********************************************************/
extern void tuya_ble_enable_debug(bool enable);
extern VOID_T tuya_ai_camera_init(VOID_T);

/***********************************************************
***********************variable define**********************
***********************************************************/
/* app thread handle */
STATIC THREAD_HANDLE ty_app_thread = NULL;

/***********************************************************
***********************function define**********************
***********************************************************/

/**
 * @brief SOC device upgrade entry
 *
 * @param[in] fw: firmware info
 *
 * @return OPRT_OK on success. Others on error, please refer to "tuya_error_code.h".
 */
STATIC OPERATE_RET __soc_dev_rev_upgrade_info_cb(IN CONST FW_UG_S *fw)
{
    TAL_PR_DEBUG("SOC Rev Upgrade Info");
    TAL_PR_DEBUG("fw->tp:%d", fw->tp);
    TAL_PR_DEBUG("fw->fw_url:%s", fw->fw_url);
    TAL_PR_DEBUG("fw->fw_hmac:%s", fw->fw_hmac);
    TAL_PR_DEBUG("fw->sw_ver:%s", fw->sw_ver);
    TAL_PR_DEBUG("fw->file_size:%u", fw->file_size);

    return OPRT_OK;
}

/**
 * @brief SOC device cloud state change callback
 *
 * @param[in] status: current status
 *
 * @return none
 */
STATIC VOID_T __soc_dev_status_changed_cb(IN CONST GW_STATUS_E status)
{
    TAL_PR_DEBUG("SOC TUYA-Cloud Status:%d", status);
    return;
}


/**
 * @brief SOC device DP query entry
 *
 * @param[in] dp_qry: DP query list
 *
 * @return none
 */
STATIC VOID_T __soc_dev_dp_query_cb(IN CONST TY_DP_QUERY_S *dp_qry)
{
    UINT32_T index = 0;

    TAL_PR_DEBUG("SOC Rev DP Query Cmd");
    if (dp_qry->cid != NULL) {
        TAL_PR_ERR("soc not have cid.%s", dp_qry->cid);
    }

    if (dp_qry->cnt == 0) {
        TAL_PR_DEBUG("soc rev all dp query");
    } else {
        TAL_PR_DEBUG("soc rev dp query cnt:%d", dp_qry->cnt);
        for (index = 0; index < dp_qry->cnt; index++) {
            TAL_PR_DEBUG("rev dp query:%d", dp_qry->dpid[index]);
            // UserTODO
        }
    }

    return;
}

/**
 * @brief SOC device format command data delivery entry
 *
 * @param[in] dp: obj dp info
 *
 * @return none
 */
STATIC VOID_T __soc_dev_obj_dp_cmd_cb(IN CONST TY_RECV_OBJ_DP_S *dp)
{

    TAL_PR_DEBUG("SOC Rev DP Obj Cmd t1:%d t2:%d CNT:%u", dp->cmd_tp, dp->dtt_tp, dp->dps_cnt);

    // invoke ai toy dp command callback
    ty_ai_toy_dp_cmd_cb(dp);

    return;
}

/**
 * @brief SOC device transparently transmits command data delivery entry
 *
 * @param[in] dp: raw dp info
 *
 * @return none
 */
STATIC VOID_T __soc_dev_raw_dp_cmd_cb(IN CONST TY_RECV_RAW_DP_S *dp)
{
    TAL_PR_DEBUG("SOC Rev DP Raw Cmd t1:%d t2:%d dpid:%d len:%u", dp->cmd_tp, dp->dtt_tp, dp->dpid, dp->len);

    return;
}

/**
 * @brief  app process when device reset
 *
 * @param[in] type: gateway reset type
 *
 * @return none
 */
STATIC VOID_T __soc_dev_reset_inform_cb(GW_RESET_TYPE_E type)
{
    TAL_PR_DEBUG("reset type %d", type);

    return;
}

/**
 * @brief SOC external network status change callback
 *
 * @param[in/out] data
 * @return STATIC
 */
STATIC OPERATE_RET __soc_dev_net_status_cb(VOID *data)
{
    STATIC BOOL_T s_syn_all_status = FALSE;

    TAL_PR_DEBUG("network status changed!");
    if (tuya_svc_netmgr_linkage_is_up(LINKAGE_TYPE_DEFAULT)) {
        TAL_PR_DEBUG("linkage status changed, current status is up");
        if (get_mqc_conn_stat()) {
            TAL_PR_DEBUG("mqtt is connected!");

            if (FALSE == s_syn_all_status) {
                s_syn_all_status = TRUE;
            }
            // UserTODO
        }
    } else {
        TAL_PR_DEBUG("linkage status changed, current status is down");

        // UserTODO
    }

    return OPRT_OK;
}

STATIC OPERATE_RET __soc_dev_reset_cb(VOID *data)
{
    __soc_dev_reset_inform_cb((GW_RESET_TYPE_E)data);
    tal_system_reset();
    return OPRT_OK;
}


/**
 * @brief mf uart init
 *
 * @param[in] baud: Baud rate
 * @param[in] bufsz: uart receive buffer size
 *
 * @return none
 */
VOID mf_uart_init_callback(UINT_T baud, UINT_T bufsz)
{
    TAL_UART_CFG_T cfg;
    memset(&cfg, 0, sizeof(TAL_UART_CFG_T));
    cfg.base_cfg.baudrate = baud;
    cfg.base_cfg.databits = TUYA_UART_DATA_LEN_8BIT;
    cfg.base_cfg.parity = TUYA_UART_PARITY_TYPE_NONE;
    cfg.base_cfg.stopbits = TUYA_UART_STOP_LEN_1BIT;
    cfg.rx_buffer_size = bufsz;

    tal_uart_init(TUYA_UART_NUM_0, &cfg);

    return;    
}

/**
 * @brief mf uart free
 *
 * @param[in] none
 *
 * @return none
 */
VOID mf_uart_free_callback(VOID)
{
    tal_uart_deinit(TUYA_UART_NUM_0);
    return;
}

/**
 * @brief mf uart send function
 *
 * @param[in] data: send data
 * @param[in] len: send data length
 *
 * @return none
 */
VOID mf_uart_send_callback(IN BYTE_T *data, IN CONST UINT_T len)
{
    tal_uart_write(TUYA_UART_NUM_0, data, len);
    return;
}

/**
 * @brief mf uart receive function
 *
 * @param[in] buf: receive buffer
 * @param[in] len: receive buffer max length
 *
 * @return receive data length
 */
UINT_T mf_uart_recv_callback(OUT BYTE_T *buf, IN CONST UINT_T len)
{
    return tal_uart_read(TUYA_UART_NUM_0, buf, len);
}

/**
 * @brief Product test callback function
 *
 * @param[in] cmd: Command
 * @param[in] data: data
 * @param[out] ret_data: Resulting data
 * @param[out] ret_len: Resulting data length
 *
 * @return OPRT_OK on success. Others on error, please refer to "tuya_error_code.h".
 */
OPERATE_RET mf_user_product_test_callback(USHORT_T cmd, UCHAR_T *data, UINT_T len, OUT UCHAR_T **ret_data, OUT USHORT_T *ret_len)
{
    /* USER todo */
    //gpio  test  refer to tuyaos_demo_examples -> src/examples/service_mf_test

    return OPRT_OK;
}

/**
 * @brief mf configure write callback functions
 *
 * @param[in] none
 *
 * @return none
 */
VOID mf_user_callback(VOID)
{
    return ;
}

/**
 * @brief Callback function before entering the production test
 *
 * @param[in] none
 *
 * @return none
 */
VOID mf_user_enter_mf_callback(VOID)
{
    return ;
}

STATIC OPERATE_RET bm_soc_dev_ota_process_cb(VOID *data)
{
    TAL_PR_DEBUG("-------------------------------------------------------[%s %d]\r\n", __func__, __LINE__);
    return OPRT_OK;
}

STATIC OPERATE_RET bm_soc_dev_ota_failed_cb(VOID *data)
{
    TAL_PR_DEBUG("-------------------------------------------------------[%s %d]\r\n", __func__, __LINE__);
    return OPRT_OK;
}

STATIC OPERATE_RET bm_soc_dev_ota_finished_cb(VOID *data)
{
    TAL_PR_DEBUG("-------------------------------------------------------[%s %d]\r\n", __func__, __LINE__);
    return OPRT_OK;
}

int bm_pre_gw_ug_cb(IN CONST FW_UG_S *fw)
{
    TAL_PR_DEBUG("[%s %d]-------------%d,%d,%s,%d,%s\r\n", __func__, __LINE__, fw->tp,fw->type,fw->fw_url,fw->file_size,fw->sw_ver);
    return OPRT_OK;
}

int bm_pre_dev_ug_cb(IN CONST CHAR_T *dev_id, IN CONST FW_UG_S *fw)
{
    TAL_PR_DEBUG("[%s %d]------------%s,%d,%d,%s,%d,%s\r\n", __func__, __LINE__, dev_id, fw->tp,fw->type,fw->fw_url,fw->file_size,fw->sw_ver);
    return OPRT_OK;
}

int bm_dev_ug_cb(IN CONST CHAR_T *dev_id, IN CONST FW_UG_S *fw)
{
    TAL_PR_DEBUG("[%s %d]------------%s,%d,%d,%s,%d,%s\r\n", __func__, __LINE__, dev_id, fw->tp,fw->type,fw->fw_url,fw->file_size,fw->sw_ver);
    return OPRT_OK;
}

VOID bm_dev_reset_cb(IN CONST CHAR_T *dev_id, IN DEV_RESET_TYPE_E type)
{
    TAL_PR_DEBUG("-------------------------------------------------------[%s %d]\r\n", __func__, __LINE__);
}
// main netlink module upgrade end notify
STATIC OPERATE_RET __main_module_upgrade_notify_cb(IN CONST FW_UG_S *fw, IN CONST INT_T download_result, IN PVOID_T pri_data)
{
    TAL_PR_DEBUG("-------------------------------------------------------[%s %d]\r\n", __func__, __LINE__);
    TAL_PR_DEBUG("fw->tp:%d", fw->tp);
    TAL_PR_DEBUG("download result:%d", download_result);

    //todo:process result and soft reset。
    //After software reboot, the device will report the current firmware version once it is connected to the network.

    return OPRT_OK;
}

STATIC OPERATE_RET __main_module_upgrage_process_cb(IN CONST FW_UG_S *fw, IN CONST UINT_T total_len,
                                            IN CONST UINT_T offset, IN CONST BYTE_T *data,
                                            IN CONST UINT_T len, OUT UINT_T *remain_len, IN PVOID_T pri_data)
{
    TAL_PR_DEBUG("total_len:%d offset:%d, data_len:%d", total_len, offset, len);

     //todo: user can process firmware data

    return OPRT_OK;
}

STATIC VOID_T bm_main_module_ug_inform_cb(INOUT BOOL_T *handled, IN CONST FW_UG_S *fw)
{
    OPERATE_RET rt = OPRT_OK;
    TAL_PR_DEBUG("[%s %d]-------------------------------------------------------tp:%d\r\n", __func__, __LINE__,fw->tp);

    // only support DEV_NM_ATH_SNGL upgrade
    if (fw->tp != DEV_NM_ATH_SNGL) {
        *handled = FALSE;
        return;
    }

    TAL_PR_DEBUG("pre dev ug, tp:%d, url:%s, hmac:%s, ver:%s, file_size:%d, diff:%d",
                 fw->tp, fw->fw_url, fw->fw_hmac, fw->sw_ver, fw->file_size, fw->diff_ota);

    *handled = TRUE;

    //start pull firmware
    TUYA_CALL_ERR_RETURN(tuya_svc_upgrade_start(NULL, fw, __main_module_upgrage_process_cb, NULL, __main_module_upgrade_notify_cb, TRUE, 0));

    return;
}

STATIC VOID_T __print_firmware_data(IN CONST BYTE_T *data, IN CONST UINT_T len)
{
    UINT_T i = 0;

    if(NULL == data || 0 == len) {
        return;
    }

    for(i = 0; i < len; i++) {
        TAL_PR_DEBUG_RAW("%02X ", data[i]);
        if(0 == ((i+1)%20)) {
            TAL_PR_DEBUG_RAW("\r\n");
        }
    }

    return;
}
STATIC VOID_T __update_firmware_version(IN CONST GW_PERMIT_DEV_TP_T tp, IN CONST CHAR_T *version)
{
    GW_ATTACH_ATTR_T attr = {0};

    TAL_PR_DEBUG("-------------------------------------------------------[%s %d]\r\n", __func__, __LINE__);
    TAL_PR_DEBUG("update tp:%d version:%s", tp, version);

    memset((UCHAR_T *)&attr, 0x00, SIZEOF(GW_ATTACH_ATTR_T));
    attr.tp  = tp;
    strncpy(attr.ver, version, SW_VER_LEN);
    tuya_iot_dev_set_attach_attr(tp, &attr);

    return;
}
#define ONE_PACK_LEN     512 

STATIC OPERATE_RET __get_attach_fw_data_cb(IN CONST FW_UG_S *fw, IN CONST UINT_T total_len, IN CONST UINT_T offset,
                                          IN CONST BYTE_T *data, IN CONST UINT_T len, OUT UINT_T *remain_len, IN PVOID_T pri_data)
{
    UINT_T pack_cnt = 0, i = 0, send_len = 0;

    TAL_PR_DEBUG("-------------------------------------------------------[%s %d]\r\n", __func__, __LINE__);
    TAL_PR_DEBUG("Rev File Data");
    TAL_PR_DEBUG("Total_len:%d ", total_len);
    TAL_PR_DEBUG("Offset:%d Len:%d", offset, len);

    pack_cnt = len/ONE_PACK_LEN;
    *remain_len = len % ONE_PACK_LEN;

    for (i=0; i<pack_cnt; i++) {
        //__print_firmware_data(&data[send_len], ONE_PACK_LEN);
        send_len += ONE_PACK_LEN;
    }

    // last pack
    if (offset + len == total_len) {
        TAL_PR_DEBUG("the last fw pack");

        if ((*remain_len) > 0) {
            //__print_firmware_data(&data[send_len], (*remain_len));
            send_len += (*remain_len);
            *remain_len = 0;
        }

        //update version
        __update_firmware_version(fw->tp, fw->sw_ver);
    }

    return OPRT_OK;
}
STATIC OPERATE_RET __attach_download_result_notify_cb(IN CONST FW_UG_S *fw, IN CONST INT_T download_result, IN PVOID_T pri_data)
{
    TAL_PR_DEBUG("-------------------------------------------------------[%s %d]\r\n", __func__, __LINE__);
    TAL_PR_DEBUG("fw->tp:%d", fw->tp);
    TAL_PR_DEBUG("download result:%d", download_result);

  return OPRT_OK;
}

STATIC INT_T __dev_rev_attatch_upgrade_info_cb(IN CONST FW_UG_S *fw)
{
    OPERATE_RET rt = OPRT_OK;

    TAL_PR_DEBUG("-------------------------------------------------------[%s %d]\r\n", __func__, __LINE__);
    TAL_PR_DEBUG("fw->tp:%d", fw->tp);
    TAL_PR_DEBUG("fw->fw_url:%s", fw->fw_url);
    TAL_PR_DEBUG("fw->fw_hmac:%s", fw->fw_hmac);
    TAL_PR_DEBUG("fw->sw_ver:%s", fw->sw_ver);
    TAL_PR_DEBUG("fw->file_size:%u", fw->file_size);

    TUYA_CALL_ERR_RETURN(tuya_iot_upgrade_gw(fw, __get_attach_fw_data_cb, \
                                             __attach_download_result_notify_cb, NULL));

    return OPRT_OK;
}

/**
 * @brief SOC device initialization
 *
 * @param[in] none
 *
 * @return OPRT_OK on success. Others on error, please refer to "tuya_error_code.h".
 */
OPERATE_RET __soc_device_init(VOID_T)
{
    OPERATE_RET rt = OPRT_OK;

    ty_subscribe_event(EVENT_RESET, "quickstart", __soc_dev_reset_cb, SUBSCRIBE_TYPE_EMERGENCY);
    ty_subscribe_event(EVENT_LINK_UP, "quickstart", __soc_dev_net_status_cb, SUBSCRIBE_TYPE_NORMAL);
    ty_subscribe_event(EVENT_LINK_DOWN, "quickstart", __soc_dev_net_status_cb, SUBSCRIBE_TYPE_NORMAL);
    ty_subscribe_event(EVENT_MQTT_CONNECTED, "quickstart", __soc_dev_net_status_cb, SUBSCRIBE_TYPE_NORMAL);

    ty_subscribe_event(EVENT_OTA_PROCESS_NOTIFY, "ota.process", bm_soc_dev_ota_process_cb, SUBSCRIBE_TYPE_NORMAL);
    ty_subscribe_event(EVENT_OTA_FAILED_NOTIFY, "ota.failed", bm_soc_dev_ota_failed_cb, SUBSCRIBE_TYPE_NORMAL);
    ty_subscribe_event(EVENT_OTA_FINISHED_NOTIFY, "ota.finished", bm_soc_dev_ota_finished_cb, SUBSCRIBE_TYPE_NORMAL);

#if (defined(UUID) && defined(AUTHKEY))
#ifndef ENABLE_KV_FILE
    ws_db_init_mf();
#endif
    /* Set authorization information
     * Note that if you use the default authorization information of the code, there may be problems of multiple users and conflicts,
     * so try to use all the authorizations purchased from the tuya iot platform.
     * Buying guide: https://developer.tuya.com/cn/docs/iot/lisence-management?id=Kb4qlem97idl0.
     * You can also apply for two authorization codes for free in the five-step hardware development stage of the Tuya IoT platform.
     * Authorization information can also be written through the production testing tool.
     * When the production testing function is started and the authorization is burned with the Tuya Cloud module tool,
     * please comment out this piece of code.
     */
#ifdef ENABLE_WIFI_SERVICE
    WF_GW_PROD_INFO_S prod_info = {UUID, AUTHKEY};
    TUYA_CALL_ERR_RETURN(tuya_iot_set_wf_gw_prod_info(&prod_info));
#else
    GW_PROD_INFO_S prod_info = {UUID, AUTHKEY};
    TUYA_CALL_ERR_RETURN(tuya_iot_set_gw_prod_info(&prod_info));
#endif

#else
    /*authorization is burned with the Tuya Cloud module tool
     *If you want to get the specific details, such as GPIO TEST,
     *please refer to the tuyaos_demo_examples -> src/examples/service_mf_test.*/
    MF_IMPORT_INTF_S intf = {0};

    intf.uart_init = mf_uart_init_callback;
    intf.uart_free = mf_uart_free_callback;
    intf.uart_send = mf_uart_send_callback;
    intf.uart_recv = mf_uart_recv_callback;

    intf.mf_user_product_test = mf_user_product_test_callback;
    intf.user_callback = mf_user_callback;
    intf.user_enter_mf_callback = mf_user_enter_mf_callback;

    TUYA_CALL_ERR_RETURN(mf_init(&intf, APP_BIN_NAME, USER_SW_VER, TRUE));

    TAL_PR_NOTICE("mf_init successfully");
#endif


    // TODO: OEM firmware: need recovery para form json config
    TY_AI_TOY_CFG_T ai_toy_cfg  = TY_AI_TOY_CFG_DEFAULT;


//#if defined(T5AI_BOARD_EVB) && T5AI_BOARD_EVB == 1   
    //wd_mf_test_close_if_write(TRUE); 
    ty_ai_toy_mf_test_init(&ai_toy_cfg);//tuya production test, please do not modify
    //TAL_PR_NOTICE("ty_ai_toy_mf_test_init");
//#endif

#if (defined(ENABLE_PRODUCT_AUTOTEST) && (ENABLE_PRODUCT_AUTOTEST == 1))
    if (prodtest_ssid_scan(500)) {
        TAL_PR_NOTICE("prodtest_ssid_scan");
        return;
    }
    TAL_PR_NOTICE("prodtest_ssid_scan ignored");
#endif

    // set wifi dtim 3
    tal_cpu_set_lp_mode(TRUE);
    tal_wifi_set_lps_dtim(3);
    tal_cpu_lp_disable();
    tal_wifi_lp_disable();

    /* Initialize TuyaOS product information */
    TY_IOT_CBS_S iot_cbs = {0};
    iot_cbs.gw_status_cb    = __soc_dev_status_changed_cb;
    //iot_cbs.gw_ug_cb        = __soc_dev_rev_upgrade_info_cb;
    iot_cbs.gw_reset_cb     = __soc_dev_reset_inform_cb;
    iot_cbs.dev_obj_dp_cb   = __soc_dev_obj_dp_cmd_cb;
    iot_cbs.dev_raw_dp_cb   = __soc_dev_raw_dp_cmd_cb;
    iot_cbs.dev_dp_query_cb = __soc_dev_dp_query_cb;

    iot_cbs.pre_gw_ug_cb = bm_pre_gw_ug_cb;
    iot_cbs.gw_ug_cb        = __dev_rev_attatch_upgrade_info_cb;
    iot_cbs.pre_dev_ug_cb = bm_pre_dev_ug_cb;          //通知我们，子设备有升级请求
    iot_cbs.dev_ug_cb = bm_dev_ug_cb;                  //通知我们子设备开始进入升级流程，并告知所需的 URL。
    iot_cbs.dev_reset_cb =bm_dev_reset_cb;             //通知子设备被重置了
    tuya_svc_upgrade_register_pre_cb(bm_main_module_ug_inform_cb);

    GW_ATTACH_ATTR_T attach_arr[] = {
        {
            .tp = DEV_NM_ATH_SNGL,
            .ver = "1.0.0",
        },
        {
            .tp = DEV_ATTACH_MOD_1,
            .ver = "1.0.0",
        },
        {
            .tp = DEV_ATTACH_MOD_2,
            .ver = "1.0.0",
        },
    };

#ifdef ENABLE_WIFI_SERVICE
#ifdef PID
    //TUYA_CALL_ERR_RETURN(tuya_iot_wf_soc_dev_init(GWCM_OLD, WF_START_AP_FIRST, &iot_cbs, PID, USER_SW_VER));
    //TUYA_CALL_ERR_RETURN(tuya_iot_wf_mcu_dev_init(GWCM_OLD, WF_START_AP_FIRST, &iot_cbs, GFW_FIRMWARE_KEY, PID, USER_SW_VER, USER_SW_VER));
    TUYA_CALL_ERR_RETURN(tuya_iot_wf_dev_init(GWCM_OLD, WF_START_AP_FIRST, &iot_cbs,GFW_FIRMWARE_KEY_TY, PID, USER_SW_VER, DEV_NM_ATH_SNGL,\
                                       attach_arr, CNTSOF(attach_arr)));
#else
    tuya_iot_oem_set(TRUE);
    TUYA_CALL_ERR_RETURN(tuya_iot_wf_soc_dev_init_param(GWCM_OLD, WF_START_AP_FIRST, &iot_cbs, GFW_FIRMWARE_KEY, GFW_FIRMWARE_KEY, USER_SW_VER));
#endif
#ifdef ENABLE_WIRED
    // init wired linkage
    TUYA_CALL_ERR_RETURN(tuya_svc_wired_init());
#endif
#else
    TUYA_CALL_ERR_RETURN(tuya_iot_soc_init(&iot_cbs, PID, USER_SW_VER));
#endif

    tuya_ble_enable_debug(false);
    app_key_init(NETWORK_CFG_PIN);
    /* AI toy initialization */
    TUYA_CALL_ERR_RETURN(log_seq_set_enable(FALSE));    // disable log sequence, 减少flash写入操作
    TUYA_CALL_ERR_RETURN(ty_ai_toy_init(&ai_toy_cfg));

    app_voice_init();
    app_pir_init();

    return 0;
}

STATIC VOID_T user_main(VOID_T)
{
    OPERATE_RET rt = OPRT_OK;

    /* Initialization, because DB initialization takes a long time,
     * which affects the startup efficiency of some devices,
     * so special processing is performed during initialization to delay initialization of DB
     */
#if OPERATING_SYSTEM == SYSTEM_LINUX
    rt= system("mkdir -p ./tuya_db_files/");
    TUYA_CALL_ERR_LOG(tuya_iot_init_params("./tuya_db_files/", NULL));
#else
    TY_INIT_PARAMS_S init_param = {0};
    init_param.init_db = TRUE;
    strcpy(init_param.sys_env, TARGET_PLATFORM);
    TUYA_CALL_ERR_LOG(tuya_iot_init_params(NULL, &init_param));
#endif

    TAL_PR_NOTICE("sdk_info:%s", tuya_iot_get_sdk_info());                        /* print SDK information */
    TAL_PR_NOTICE("name:%s:%s", APP_BIN_NAME, USER_SW_VER);                       /* print the firmware name and version */
    TAL_PR_NOTICE("firmware compiled at %s %s", __DATE__, __TIME__);              /* print firmware compilation time */
    TAL_PR_NOTICE("system reset reason:[%d]", tal_system_get_reset_reason(NULL)); /* print system reboot causes */

    tal_log_set_manage_attr(TAL_LOG_LEVEL_DEBUG);
    // tal_log_set_manage_attr(TAL_LOG_LEVEL_INFO);

#if defined(ENABLE_TUYA_UI) && ENABLE_TUYA_UI == 1
    tuya_ai_display_init();
#endif

    /* Initialization device */
    TAL_PR_DEBUG("device_init in");
    TUYA_CALL_ERR_LOG(__soc_device_init());
    app_touch_init();
//#if defined(T5AI_BOARD_EVB) && T5AI_BOARD_EVB == 1
    TUYA_CALL_ERR_LOG(tuya_ai_toy_battery_init());
//#endif

#if defined(ENABLE_TUYA_CAMERA) && ENABLE_TUYA_CAMERA == 1
    tuya_ai_camera_init();
#endif

    return;
}

int reset_netconfig_init(VOID);
/**
* @brief  task thread
*
* @param[in] arg:Parameters when creating a task
* @return none
*/
STATIC VOID_T tuya_app_thread(VOID_T *arg)
{
    tuya_base_utilities_init();

    /* Initialization LWIP first!!! */
#if defined(ENABLE_LWIP) && (ENABLE_LWIP == 1)
    TUYA_LwIP_Init();
#endif

    reset_netconfig_init();//do net config reset by switching power key 3 times

    user_main();

    tal_thread_delete(ty_app_thread);
    ty_app_thread = NULL;
}

/**
 * @brief user entry function
 *
 * @param[in] none:
 *
 * @return none
 */
#if OPERATING_SYSTEM == SYSTEM_LINUX
INT_T main(INT_T argc, CHAR_T **argv)
#else
VOID_T tuya_app_main(VOID)
#endif
{
    extern VOID_T tkl_system_psram_malloc_force_set(BOOL_T enable);
    tkl_system_psram_malloc_force_set(TRUE);

    THREAD_CFG_T thrd_param = {4096, THREAD_PRIO_2, "tuya_app_main"};
    tal_thread_create_and_start(&ty_app_thread, NULL, NULL, tuya_app_thread, NULL, &thrd_param);
#if OPERATING_SYSTEM == SYSTEM_LINUX
    while (1) {
        tal_system_sleep(1000);
    }
#endif
}

/* uncomment following comment to disable asr or enbale ty vad */
#if 1
/*
    * @brief  tuya_asr_enable
    * @param  none
    * 
    * @return BOOL_T return TRUE if enable asr, FALSE if disable asr
    * @note   this function is weak, user can override it
    *         if user want to disable asr, just return FALSE
 */
BOOL_T tuya_asr_enable(VOID_T)
{
    return TRUE;
}

/*
    * @brief  tuya_vad_enable
    * @param  none
    * 
    * @return uint8_t return 1 if enable ty vad
    * @note   this function is weak, user can override it
    *         if user want to disable vad, just return FALSE
 */
uint8_t tuya_vad_enable(void)
{
    return TRUE;
}
#endif
