#include "server/audio_server.h"
#include "server/server_core.h"
#include "server/ai_server.h"
#include "system/app_core.h"
#include "system/wait.h"
#include "system/timer.h"
#include "system/includes.h"
#include "wifi/wifi_connect.h"
#include "http/http_cli.h"
#include "generic/circular_buf.h"
#include "os/os_api.h"
#include "syscfg/syscfg_id.h"
#include "event/key_event.h"
#include "event/device_event.h"
#include "event/net_event.h"
#include "event/bt_event.h"
#include "fs/fs.h"
#include <time.h>
#include <curl/curl.h>
#include "web_socket/websocket_api.h"

#include "app_config.h"
#include "storage_device.h"
#include "syscfg_id.h"
#include "asm/sfc_norflash_api.h"

#include "app_power_manage.h"
#include "net/assign_macaddr.h"
#include "net/config_network.h"
#include "net/assign_macaddr.h"

#include "btstack/avctp_user.h"
#include "btctrler/btctrler_task.h"
#include "classic/hci_lmp.h"

#include "json_c/json_object.h"
#include "json_c/json_tokener.h"
#include "network_download/net_download.h"
#include "brtc_wrapper.h"
#include "sa_audio.h"

#define VOLUME_STEP         10
#define GAIN_STEP           5
#define MIN_VOLUME_VALUE	5
#define MAX_VOLUME_VALUE	100
#define INIT_VOLUME_VALUE   50

#define PRODUCT_UUID_SIZE  32
#define PRODUCT_SN_SIZE	   32

// #define POWER_ON_FILE       CONFIG_VOICE_PROMPT_FILE_PATH"poweron.mp3"
// #define FAIL_FILE           CONFIG_VOICE_PROMPT_FILE_PATH"AsrEmpty.mp3"
// #define NET_UNVALID_FILE    CONFIG_VOICE_PROMPT_FILE_PATH"AiAsrFail.mp3"
// #define CANCEL_FILE         CONFIG_VOICE_PROMPT_FILE_PATH"ring.mp3"
// #define BT_OPEN_FILE        CONFIG_VOICE_PROMPT_FILE_PATH"BtOpen.mp3"
// #define NET_CFG_ENTER_FILE  CONFIG_VOICE_PROMPT_FILE_PATH"NetCfgEnter.mp3"
// #define NET_CFG_SUCC_FILE   CONFIG_VOICE_PROMPT_FILE_PATH"NetCfgSucc.mp3"
// #define NET_CFG_FAIL_FILE   CONFIG_VOICE_PROMPT_FILE_PATH"NetCfgFail.mp3"
// #define NET_CFG_TO_FILE     CONFIG_VOICE_PROMPT_FILE_PATH"NetCfgTo.mp3"
// #define NET_EMPTY_FILE      CONFIG_VOICE_PROMPT_FILE_PATH"NetEmpty.mp3"
// #define NET_CONN_FILE       CONFIG_VOICE_PROMPT_FILE_PATH"NetConnting.mp3"
// #define NET_DISC_FILE       CONFIG_VOICE_PROMPT_FILE_PATH"NetDisc.mp3"
// #define SSID_RECV_FILE      CONFIG_VOICE_PROMPT_FILE_PATH"SsidRecv.mp3"
// #define SER_DISC_FILE       CONFIG_VOICE_PROMPT_FILE_PATH"SerDiscon.mp3"
// #define OTA_IN_FILE         CONFIG_VOICE_PROMPT_FILE_PATH"OtaKey.mp3"
// #define OTA_SUCC_FILE       CONFIG_VOICE_PROMPT_FILE_PATH"OtaSuccess.mp3"
// #define OTA_FAIL_FILE       CONFIG_VOICE_PROMPT_FILE_PATH"OtaFailed.mp3"
// #define VOLUME_UP_FILE      CONFIG_VOICE_PROMPT_FILE_PATH"VolumeUp.mp3"
// #define VOLUME_DOWN_FILE    CONFIG_VOICE_PROMPT_FILE_PATH"VolumeDown.mp3"
// #define VOLUME_FULL_FILE    CONFIG_VOICE_PROMPT_FILE_PATH"VolumeFull.mp3"
// #define VOLUME_FILE          CONFIG_VOICE_PROMPT_FILE_PATH"Volume.mp3"

#define HOST_NAME           "180.101.51.191"
// #define HOST_NAME           "183.6.105.223:20001"
// #define HOST_NAME        "183.6.105.223:20001"
#define WS_DEMO_URL         "ws://"HOST_NAME"/ws_process_audio"
// #define WS_DEMO_URL         "ws://"HOST_NAME"/ws_process_audio_buddhism"
#define REQ_BUFFER_SIZE     (256 * 1024)
#define RES_BUFFER_SIZE     (1024 * 1024)
#define RECV_BUFFER_SIZE    (512)
#define SEND_BUFFER_SIZE    (2160)

#define MAX_RECOVER_INTERVAL 20000

#define STOP_MSG            ("The pickup time exceeds the threshold")
#define DONE_MSG            ("done")
#define NET_MUSIC_MSG       ("http")

// #define SH_OS_TASKQ_POST(name,argc, ...)                       \
//     do{                                                         \
//         int err =  os_taskq_post(name,argc, __VA_ARGS__);       \
//         if(err){                                                \
//             printf("\n %s %d err = %d\n",__func__,__LINE__,err); \
//         }                                                       \
//     }while(0)

// enum {
//     SH_WS_CONN = 0,
//     SH_WS_SEND_AUDIO,
//     SH_WS_EXIT,
// };

struct ws_interact_hdl {
    // websocket连接
    OS_MUTEX websockets_op_mutex;
    struct websocket_struct websockets_info;

    // 电量
    int battery_per;

    // 网络
    int reconnecting;
    int net_dhcp_ready;
    int net_connected;
    int bt_enable;
    u16 coexistence_timer;

    // // 音乐播放
    // volatile u8 has_net_music;      // 是否有网络音乐需要播放，1：是
    // volatile u8 is_net_music;       // 是否在播放网络音乐，1：是
    // char *net_music_url;            // 网络音乐播放地址
    // u16 wait_download;              // 异步等待下载音乐标志，>0:等待下载中
    // int download_ready;             // 音乐缓冲完成标志，1：完成
    // void *net_file;                 // 网络音乐文件
};

static struct ws_interact_hdl ws_interact_handler;

#define __this (&ws_interact_handler)
extern void ble_cfg_net_result_notify(int event);
extern void wifi_return_sta_mode(void);
extern void bt_connection_disable(void);
extern void bt_connection_enable(void);
extern int app_music_bt_event_handler(struct sys_event *event);
extern void start_http_upgrade_task(void *priv);

volatile uint8_t brtc_is_running = 0; // 0 未运行，1 运行
volatile uint8_t brtc_notice_net_connect_failed_times = 3;  // 网络连接失败，通知3次
volatile u32 last_time = 0;

volatile bool  g_power_off = true;
bool power_off_wake_up() {
    g_power_off = true;
}

static void websockets_disconnect(struct websocket_struct *websockets_info);
static int open_audio_dec(void* priv);
static int net_music_dec_file(const char *url);
void set_brtc_status(int status){
    brtc_is_running = status;
}
// 模式初始化
static int ws_interact_init(void)
{

    extern void get_fw_version();
    get_fw_version();

    memset(__this, 0, sizeof(struct ws_interact_hdl));

    return 0;
}

// 模式退出
static void ws_interact_mode_exit(void)
{
    printf("------ws_interact mode exit\n");

    SH_OS_TASKQ_POST("ws_task", 1, SH_WS_EXIT);
}

extern void brtc_ai_agent_task_open(void* priv);
extern void brtc_ai_agent_task_close(void* priv);

// 按键事件
static int ws_interact_key_click(struct key_event *key)
{
    int ret = true;
    int ready = 0;
    //网络连接失败，请配置网络

    if (last_time > 0 &&(timer_get_ms() < last_time + MAX_RECOVER_INTERVAL)) {
        play_mix_file(AGENT_RECOVER_FREQUEN);
        os_time_dly(500); //等待退出，后重新链接
        return ret;
    }
    last_time =  timer_get_ms();
    //单击重启现有的agent
    if(app_brtc_agent_can_exit()) {
        play_mix_file(AGENT_RECOVER_NOTICE);
        app_sdk_should_close(true);//配置时候关闭agent
        os_time_dly(500); //等待退出，后重新链接
    }

    enum wifi_sta_connect_state state;
    printf("ws_interact---> key value: %d  <---__this->net_dhcp_ready: %d", key->value, __this->net_dhcp_ready);
    switch (key->value) {
    case KEY_OK:
        printf("----------ws_interact---> brtc_is_running: %d --1--", brtc_is_running);
        malloc_stats();
        if (brtc_is_running){
        //    printf("ws_interact---> brtc_is_running: %d <---", brtc_is_running);
        //    os_time_dly(100);
        //    baidu_chat_agent_demo_close();
        //    brtc_is_running = 1;
            break;
        }
        thread_fork("brtc_ai_agent_task_close", 21, 16 * 1024, 128, NULL, (void*)brtc_ai_agent_task_close, NULL);
        brtc_is_running = 1;
        ret = thread_fork("brtc_ai_agent_task_open", 21, 16 * 1024, 128, NULL, (void*)brtc_ai_agent_task_open, NULL);
        // // low_power_all_group_force_sleep(10000000);
        // if (get_sa_audio_handler()->enc_flag) {
        //     // 当前正在录音，忽略按键功能
        // } else if (get_sa_audio_handler()->dec_run_flag || get_sa_audio_handler()->is_net_music) {
        //     // 当前正在播放，发送停止生成消息，取消播放
        //     get_sa_audio_handler()->recv_status = 1;
        //     if (get_sa_audio_handler()->is_net_music) {
        //         net_music_dec_end();
        //     } else {
        //         close_audio_dec();
        //     }
        //     websockets_disconnect(&__this->websockets_info);
        //     play_file(CANCEL_FILE);
        // } else {
        //     // 当前空闲或正在进行音频播放，结束播放，开启录音
        //     state = wifi_get_sta_connect_state();
        //     printf("**************wifi_get_sta_connect_state: %d ********************\n", state);
        //     if (WIFI_STA_NETWORK_STACK_DHCP_SUCC == state) {
        //         // SH_OS_TASKQ_POST("ws_task", 1, SH_WS_CONN);
        //         // close_audio_dec();
        //         // printf("----------------do mic audio record");
        //         // open_audio_enc();
        //         // close_audio_dec();

        //     } else {
        //         close_audio_dec();
        //         play_file(NET_UNVALID_FILE);
        //     }
        // }
        break;
    default:
        ret = false;
        break;
    }

    return ret;
}
bool brtc_aiagent_auto_open() {
    struct key_event mock_key;
    mock_key.value = KEY_OK;
    ws_interact_key_click(&mock_key);
}

void ws_interact_ota_event_notify(int event, int type) {
    if (event == AI_SERVER_EVENT_UPGRADE) {
        sys_power_auto_shutdown_pause();
        key_event_disable();
        play_mix_file(OTA_IN_FILE);
#ifdef CONFIG_LOW_POWER_ENABLE
        low_power_hw_unsleep_lock();
#endif
        //start_http_upgrade_task(NULL);
    } else if (event == AI_SERVER_EVENT_UPGRADE_SUCC) {
        // system_reset();
        play_mix_file(OTA_SUCC_FILE);
    } else if (event == AI_SERVER_EVENT_UPGRADE_FAIL) {
        os_time_dly(1000); // 10s
        key_event_enable();
        if (type == 0) {
            // 任务创建失败
        } else if (type == 1) {
            // 网络未连接
        } else if (type == 2) {
            // 版本获取失败
        } else if (type == 3) {
            // 已是最新版本
        } else if (type == 4) {
            // 下载任务创建失败
        } else if (type == 5) {
            // 下载失败
        } else {
        }
        play_mix_file(OTA_FAIL_FILE);
        sys_power_auto_shutdown_resume();
#ifdef CONFIG_LOW_POWER_ENABLE
        low_power_hw_unsleep_unlock();
#endif
    }
}

static int app_music_bt_event_handler_pretreatment(struct bt_event *event)
{
    return 0;
}

static void switch_rf_coexistence_timer(void *p)
{
    __this->coexistence_timer = 0;

    switch_rf_coexistence_config_unlock();

#if defined CONFIG_BT_ENABLE && !BT_SUPPORT_WIFI_CFG_COEXISTENCE
    if (!is_in_config_network_state())
#endif
    {
        switch_rf_coexistence_config_table(0);
    }
}

static void app_net_config(void)
{
    __this->reconnecting = 0;
#ifdef CONFIG_ASSIGN_MACADDR_ENABLE
    cancel_server_assign_macaddr();
#endif

    if (!is_in_config_network_state()) {
        printf("------config_network_start\n");
        sys_power_auto_shutdown_pause();

        if (__this->coexistence_timer) {
            sys_timeout_del(__this->coexistence_timer);
            __this->coexistence_timer = 0;
            switch_rf_coexistence_config_unlock();
        }

#if defined CONFIG_BT_ENABLE && !BT_SUPPORT_WIFI_CFG_COEXISTENCE
        if (__this->bt_enable) {
            __this->bt_enable = 0;
            bt_connection_disable();
        }
#endif
        __this->net_connected = 0;
        play_file(NET_CFG_ENTER_FILE);
#ifdef CONFIG_SERVER_ASSIGN_PROFILE
        dev_profile_uninit();
#endif
        config_network_start();
    } else {
        printf("------config_network_stop\n");
        play_file(NET_CONN_FILE);
        config_network_stop();
        wifi_return_sta_mode();
#if defined CONFIG_BT_ENABLE && !BT_SUPPORT_WIFI_CFG_COEXISTENCE
        if (__this->bt_enable) {
            __this->bt_enable = 0;
            bt_connection_disable();
        }
#endif
        sys_power_auto_shutdown_resume();
    }
}

// 按键事件
static int ws_interact_key_double_click(struct key_event *key)
{
    int ret = true;
    int ready = 0;
    enum wifi_sta_connect_state state;
    printf("ws_interact---> key value: %d <---",key->value);
    switch (key->value) {
    case KEY_OK:
        printf("------switch_net_config\n");
        // close_audio_enc();
        app_sdk_should_close(false);//配置时候关闭agent
        close_audio_dec();
        if (__this->bt_enable == 0) {
            __this->bt_enable = 1;
            bt_connection_enable();
        }
        app_net_config();
        break;
    default:
        ret = false;
        break;
    }

    return ret;
}

// 5次按键事件
static int ws_interact_key_firth_click(struct key_event *key)
{
    int ret = true;
    int ready = 0;
    enum wifi_sta_connect_state state;
    printf("ws_interact---> 5 key value: %d <---",key->value);
    switch (key->value) {
    case KEY_OK:
        ws_interact_ota_event_notify(AI_SERVER_EVENT_UPGRADE, 0);
        break;
    default:
        ret = false;
        break;
    }

    return ret;
}

static void power_delay_off(void *priv)
{
    os_time_dly(400);// 3秒 300个时钟 300*10

    sys_power_poweroff();

}

static int ws_interact_key_event_handler(struct key_event *key)
{
    if (is_in_config_network_state() && (key->action != KEY_EVENT_DOUBLE_CLICK || key->value != KEY_OK)) {
        //配网模式下只有配网键能起作用
        printf("------key event filter while config network\n");
        return true;
    }
    switch (key->action) {
    case KEY_EVENT_CLICK:
        return ws_interact_key_click(key);

    case KEY_EVENT_LONG:

        if (g_power_off) {
            g_power_off = true;
            //进入待机模式
            play_mix_file(DEVICE_POWER_OFF);
            int ret = thread_fork("power_off_task", 21, 1024 * 2, 128, NULL, (void*)power_delay_off, NULL);
        }


        //return set_dec_volume(VOLUME_STEP);
        //return ws_interact_key_click(key);
        return true;
    case KEY_EVENT_HOLD:
        printf("  [KEY_EVENT_HOLD]  \n");
        break;
    case KEY_EVENT_UP:
        // printf("  [KEY_EVENT_UP]  \n");
        break;
    case KEY_EVENT_DOUBLE_CLICK:
        printf("  [KEY_EVENT_DOUBLE_CLICK]  \n");
        return ws_interact_key_double_click(key);
    case KEY_EVENT_FIRTH_CLICK:
        printf("  [KEY_EVENT_FIRTH_CLICK]  \n");
        return ws_interact_key_firth_click(key);
    default:
        break;
    }

    return true;
}

static int ws_interact_device_event_handler(struct sys_event *sys_eve)
{
    struct device_event *device_eve = (struct device_event *)sys_eve->payload;

    if (sys_eve->from == DEVICE_EVENT_FROM_POWER) {
        if (device_eve->event == POWER_EVENT_POWER_CHANGE) {
            __this->battery_per = sys_power_get_battery_persent();
            printf("-----power_change: %d\n", __this->battery_per);
        } else if (device_eve->event == POWER_EVENT_POWER_WARNING) {
            printf("-----power_warning: %d\n", __this->battery_per);
        } else if (device_eve->event == POWER_EVENT_POWER_LOW) {
            printf("-----power_low: %d\n", __this->battery_per);
        } else if (device_eve->event == POWER_EVENT_POWER_AUTOOFF) {
            printf("-----power_autooff: %d\n", __this->battery_per);
        } else if (device_eve->event == POWER_EVENT_POWER_CHARGE) {
            printf("-----power_charge: %d\n", __this->battery_per);
        }
    }

    return true;
}

static int ws_interact_net_event_handler(struct net_event *event)
{
    if (ASCII_StrCmp(event->arg, "net", 4) == 0) {
        switch (event->event) {
        case NET_CONNECT_TIMEOUT_NOT_FOUND_SSID:
        case NET_CONNECT_ASSOCIAT_FAIL:
            printf("------wifi_connect_fail----------------------------------------\r\n");
            if(brtc_notice_net_connect_failed_times > 0) {
                brtc_notice_net_connect_failed_times --;
                play_mix_file(NET_CFG_FAIL_FILE);
            }
            ble_cfg_net_result_notify(event->event);
            //app_sdk_should_close();
            break;
        case NET_EVENT_SMP_CFG_FIRST:
            printf("------wifi empty\n");
            play_mix_file(NET_EMPTY_FILE);
            break;
        case NET_EVENT_SMP_CFG_FINISH:
            printf("------recv ssid\n");
            if (is_in_config_network_state()) {
                play_mix_file(SSID_RECV_FILE);
                config_network_stop();
                config_network_connect();
                sys_power_auto_shutdown_resume();
            }
            break;
        case NET_EVENT_CONNECTED:
            printf("------NET_EVENT_CONNECTED\n");
            __this->net_dhcp_ready = 1;
            brtc_notice_net_connect_failed_times = 3;
            if (!is_in_config_network_state()) {
                ble_cfg_net_result_notify(event->event);
                play_mix_file(NET_CFG_SUCC_FILE);
                __this->reconnecting = 0;
#ifdef CONFIG_SERVER_ASSIGN_PROFILE
                dev_profile_init();
#endif
            }
            __this->net_connected = 1;
            if (__this->coexistence_timer) {
                sys_timeout_del(__this->coexistence_timer);
                __this->coexistence_timer = 0;
                switch_rf_coexistence_config_unlock();
                switch_rf_coexistence_config_table(0);
            }
            break;
        case NET_EVENT_DISCONNECTED:
            printf("------NET_EVENT_DISCONNECTED\n");
            if (!__this->net_dhcp_ready) {
                break;
            }
            canceladdrinfo();
            __this->net_dhcp_ready = 0;
            // get_sa_audio_handler()->recv_status = 1;
            if (__this->net_connected && !is_in_config_network_state() && !__this->reconnecting) {
                play_mix_file(NET_DISC_FILE);

                //退出智能体
                app_sdk_should_close(false);

            }
            __this->net_connected = 0;
            break;
        case NET_EVENT_SMP_CFG_TIMEOUT:
            printf("------wifi connect timeout\n");
            if (is_in_config_network_state()) {
                play_mix_file(NET_CFG_TO_FILE);
            }
            break;
        case NET_SMP_CFG_COMPLETED:
            break;
        case NET_EVENT_DISCONNECTED_AND_REQ_CONNECT:
            wifi_return_sta_mode();
            break;
        case NET_NTP_GET_TIME_SUCC:	//NTP获取成功事件返回
            break;
        default:
            break;
        }
    }

    return true;
}

static int brtc_interact_mode_init(void)
{
    printf("------brtc_interact mode init\n");
    extern void get_fw_version(void);
    //get_fw_version();

    u8 flash_uid[16];
    memset(flash_uid, 0, 16);
    memcpy(flash_uid, get_norflash_uuid(), 16);
    printf("flash_uid: %s", flash_uid);

    char uid_str[33] = {0};
    for (int i = 0; i < 16; i++) {
        // %02X 格式输出两位大写十六进制数字，%02x 小写十六进制数字
        sprintf(&uid_str[i * 2], "%02X", flash_uid[i]);
    }
    printf("Flash UID: %s\n", uid_str);

    memset(__this, 0, sizeof(struct ws_interact_hdl));

    sa_audio_init();
    os_mutex_create(&__this->websockets_op_mutex);
    // play_file(POWER_ON_FILE);
    // thread_fork("ws_task", 15, 2 * 1024, 256, NULL, ws_task, NULL);

    // int ret = thread_fork("brtc_ai_agent_task", 21, 1024 * 16, 128, NULL, (void*)brtc_ai_agent_task, NULL);
    // printf("ret = %d\n", ret);

    return 0;
}

static int ws_interact_event_handler(struct application *app, struct sys_event *event)
{
    switch (event->type) {
    case SYS_KEY_EVENT:
        return ws_interact_key_event_handler((struct key_event *)event->payload);
    case SYS_DEVICE_EVENT:
        return ws_interact_device_event_handler(event);
    case SYS_NET_EVENT:
        return ws_interact_net_event_handler((struct net_event *)event->payload);
    case SYS_BT_EVENT:
        if (event->from == BT_EVENT_FROM_CON) {
            app_music_bt_event_handler_pretreatment((struct bt_event *)event->payload);
        }
        return app_music_bt_event_handler(event);
    default:
        return false;
    }
}

static int ws_interact_state_machine(struct application *app, enum app_state state, struct intent *it)
{
    printf("mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmachine state:%d\r\n", state);
    switch (state) {
    case APP_STA_CREATE:
        break;
    case APP_STA_START:
        brtc_interact_mode_init();
        break;
    case APP_STA_PAUSE:
        break;
    case APP_STA_RESUME:
        break;
    case APP_STA_STOP:
        ws_interact_mode_exit();
        break;
    case APP_STA_DESTROY:
        break;
    }

    return 0;
}

static const struct application_operation ws_interact_ops = {
    .state_machine  = ws_interact_state_machine,
    .event_handler 	= ws_interact_event_handler,
};

REGISTER_APPLICATION(ws_interact) = {
    .name 	= "brtc_interact",
    .ops 	= &ws_interact_ops,
    .state  = APP_STA_DESTROY,
};
