#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 "baidu_chat_agents_engine.h"
#include "http/http_cli.h"

#include "app_config.h"
#include "storage_device.h"
#include "syscfg_id.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"

#define CONFIG_STORE_VOLUME
#define VOLUME_STEP         50
#define GAIN_STEP           5
#define MIN_VOLUME_VALUE	5
#define MAX_VOLUME_VALUE	100
#define INIT_VOLUME_VALUE   30

#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 WS_DEMO_URL         "ws://"HOST_NAME"/ws_process_audio"
#define REQ_BUFFER_SIZE     (256 * 1024)
#define RES_BUFFER_SIZE     (1024 * 1024)
#define RECV_BUFFER_SIZE    (512)
#define SEND_BUFFER_SIZE    (2160)

#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 {
    struct server *enc_server;      // 编码服务
    struct server *dec_server;      // 解码服务
    u8 volume;                      // 音频播放音量，50
    u8 gain;                        // 音频采集音量，100
    u8 channel;                     // 音频采集通道数，1
    char *format;                   // 音频格式，mp3
    const char *sample_source;      // 音频采集源，mic
    char *play_source;              // 音频播放源，dac
    int sample_rate;                // 音频采集采样率，16000
    u32 enc_time_msec;              // 音频采集时长ms，0：一直录; 60*1000ms

    // 音频采集
    volatile u8 enc_flag;           // 音频采集标志位，1：开始
    void *mic_buf;                  // 音频采集缓冲区，大小1MB
    u32 write_size;                 // 音频已采集大小
    u32 send_size;                  // 音频已发送大小
    OS_SEM mic_rsem;                // 音频读信号量

    // 音频播放
    FILE *speaker_fp;               // 音频播放文件描述符，play_file用
    void *speaker_buf;              // 音频播放（接收）缓冲区，大小1MB
    cbuffer_t speaker_cbuf;         // 音频播放（接收）循环缓冲区，基于speaker_buf
    u32 recv_size;                  // 已接收音频数据长度
    u32 play_size;                  // 当前播放长度
    OS_SEM r_sem;                   // 读音频数据信号量
    volatile u8 dec_run_flag;       // 解码器播放标志，1：开始
    volatile u8 dec_ready_flag;     // 解码器就绪标志位，1：开始
    volatile u8 dec_status;         // 解码器运行标志位，1：开始
    volatile u8 recv_status;        // 音频接收完成状态，1：完成
    u8 dec_server_status;

    // 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);

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);
static int websockets_client_send_jl(struct websocket_struct *websockets_info, u8 *buf, int len, char type);

//设置音量大小
static int set_dec_volume(int step)
{
    union audio_req req = {0};
    union ai_req ai = {0};

    int volume = __this->volume + step;
    if (volume < MIN_VOLUME_VALUE) {
        volume = MIN_VOLUME_VALUE;
    } else if (volume > MAX_VOLUME_VALUE) {
        volume = MAX_VOLUME_VALUE;
#ifdef CONFIG_VOICE_PROMPT_FILE_PATH
        play_file(CONFIG_VOICE_PROMPT_FILE_PATH"VolumeFull.mp3");
#endif
    }
    if (volume == __this->volume) {
        return -1;
    }
    __this->volume = volume;

    printf("set_dec_volume: %d\n", volume);
#ifdef CONFIG_VOICE_PROMPT_FILE_PATH
    if (volume == MAX_VOLUME_VALUE) {
        play_file(CONFIG_VOICE_PROMPT_FILE_PATH"VolumeFull.mp3");
    } else {
        play_file(CONFIG_VOICE_PROMPT_FILE_PATH"Volume.mp3");
    }
#endif

    req.dec.cmd     = AUDIO_DEC_SET_VOLUME;
    req.dec.volume  = volume;
    server_request(__this->dec_server, AUDIO_REQ_DEC, &req);

#ifdef CONFIG_STORE_VOLUME
    syscfg_write(CFG_MUSIC_VOL, &__this->volume, sizeof(__this->volume));
#endif

    return 0;
}

// static int set_dec_volume(int step)
// {
//     union audio_req req = {0};

//     int volume = __this->volume + step;
//     if (volume < MIN_VOLUME_VALUE) {
//         volume = MIN_VOLUME_VALUE;
//     } else if (volume > MAX_VOLUME_VALUE) {
// #ifdef CONFIG_VOICE_PROMPT_FILE_PATH
//         play_file(CONFIG_VOICE_PROMPT_FILE_PATH"VolumeFull.mp3");
// #endif
//         volume = MAX_VOLUME_VALUE;
//     }
//     if (volume == __this->volume) {
//         return -EINVAL;
//     }
//     __this->volume = volume;

// #ifdef CONFIG_UI_ENABLE
//     os_taskq_post(POST_TASK_NAME, 2, UI_MSG_SET_VOLUME, volume);
// #endif

//     printf("set_dec_volume: %d\n", volume);

// #ifdef CONFIG_DEC_DIGITAL_VOLUME_ENABLE
// #if TCFG_USER_EMITTER_ENABLE
//     if (get_bt_emitter_audio_server() && __this->digital_vol_hdl && __this->dec_server) {
//         return user_audio_digital_volume_set(__this->digital_vol_hdl, volume, 1);
//     }
// #endif
// #if TCFG_USER_VIRTUAL_PLAY_ENABLE
//     if (check_user_virtual_audio_if_running() && __this->digital_vol_hdl && __this->dec_server) {
//         return user_audio_digital_volume_set(__this->digital_vol_hdl, volume, 1);
//     }
// #endif
// #endif

// #ifdef CONFIG_VOICE_PROMPT_FILE_PATH
//     if (volume == MAX_VOLUME_VALUE) {
//         play_file(CONFIG_VOICE_PROMPT_FILE_PATH"VolumeFull.mp3");
//     } else {
//         play_file(CONFIG_VOICE_PROMPT_FILE_PATH"Volume.mp3");
//     }
// #endif

//     if (!__this->dec_server) {
//         return -EFAULT;
//     }

//     req.dec.cmd     = AUDIO_DEC_SET_VOLUME;
//     req.dec.volume  = volume;
//     server_request(__this->dec_server, AUDIO_REQ_DEC, &req);

//     return 1;
// }

static void websockets_callback(u8 *buf, u32 len, u8 type)
{
    // printf("wbs recv msg : %s, len:%d\n", buf, len);
    bool is_fin = type & 0x80;
    u8 data_type = type & 0x0f;
    switch (data_type) {
    case WCT_SEQ:
        if (!is_fin) {
            printf("------not fin\n");
        } else {
            printf("------is fin\n");
        }
        break;
    case WCT_TXTDATA:
        printf("------txt data: %s\n", buf);
        json_object *parse = NULL;
        parse = json_tokener_parse(buf);
        if (!parse) {
            printf("json parse error\n");
            return;
        }
        char *content = json_object_get_string(json_object_object_get(parse, "content"));
        if (strncmp(content, STOP_MSG, strlen(STOP_MSG)) == 0) {
            // 收到停止录音消息
            close_audio_enc();
            __this->dec_run_flag = 1;
        } else if (strncmp(content, DONE_MSG, strlen(DONE_MSG)) == 0) {
            // 收到回答发送结束消息
            printf("------receive done\n");
            __this->recv_status = 1;
        } else if (strncmp(content, NET_MUSIC_MSG, strlen(NET_MUSIC_MSG)) == 0) {
            // 收到网络音乐播放消息
            __this->has_net_music = 1;
            memset(__this->net_music_url, 0, 512);
            memcpy(__this->net_music_url, content, strlen(content));
        }
        json_object_put(parse);
        break;
    case WCT_BINDATA:
        // 收到二进制音频数据
        printf("------bin data, len:%d\n", len);
        if (!__this->dec_run_flag) {
            return;
        }
        u32 wlen = 0;
        while (len > 0) {
            size_t to_write = (len > RECV_BUFFER_SIZE) ? RECV_BUFFER_SIZE : len;
            wlen = cbuf_write(&__this->speaker_cbuf, buf, to_write);
            if (wlen) {
                os_sem_post(&__this->r_sem);
                __this->recv_size += to_write;
                //音频下载成功，或缓存成功，打开解码器，开始播放
                if (__this->recv_size >= 1 * 1024 && __this->dec_status == 0) {
                    if (thread_fork("open_audio_dec", 10, 1024, 0, NULL, open_audio_dec, NULL) != OS_NO_ERR) {
                        printf("open_audio_dec thread fork fail\n");
                    }
                    __this->dec_status = 1;
                }
            }
            // 更新指针和剩余数据大小
            buf = (char *)buf + to_write; // 移动指针
            len -= to_write;          // 减少剩余大小
        }

        break;
    case WCT_DISCONN:
        printf("------disconnect\n");
        close_audio_enc();
        __this->recv_status = 1;
        break;
    case WCT_PING:
        break;
    case WCT_PONG:
        break;
    case WCT_END:
        break;
    default:
        break;
    }
}

static void websockets_send_device_info(struct websocket_struct *websockets_info)
{
    struct json_object *obj = json_object_new_object();
    struct json_object *dev_info = json_object_new_object();

    u8 sn[PRODUCT_SN_SIZE + 1] = {0};
    syscfg_read(CFG_PRODUCT_SN_INDEX, sn, PRODUCT_SN_SIZE);
    u8* sn_str = NULL;
    asprintf(&sn_str, "%s", sn);
    //printf("device sn: %d %s\n", rscorr, sn);

    json_object_object_add(dev_info, "sn", json_object_new_string(sn_str));
    json_object_object_add(dev_info, "name", json_object_new_string("test"));
    json_object_object_add(obj, "device", dev_info);

    char *json_str = json_object_to_json_string(obj);
    printf("device info: %s\n", json_str);
    // websockets_send(__this->websockets_info, (u8 *)json_str, strlen(json_str), WCT_TXTDATA);
    websockets_client_send_jl(websockets_info, (u8 *)json_str, strlen(json_str), WCT_TXTDATA);
    free(json_str);
    json_object_put(obj);

}

static void websockets_client_reg(struct websocket_struct *websockets_info, char mode)
{
    memset(websockets_info, 0, sizeof(struct websocket_struct));
    websockets_info->_init           = websockets_client_socket_init;
    websockets_info->_exit           = websockets_client_socket_exit;
    websockets_info->_handshack      = webcockets_client_socket_handshack;
    websockets_info->_send           = websockets_client_socket_send;
    websockets_info->_recv_thread    = websockets_client_socket_recv_thread;
    websockets_info->_heart_thread   = websockets_client_socket_heart_thread;
    websockets_info->_recv_cb        = websockets_callback;
    websockets_info->_recv           = NULL;

    websockets_info->websocket_mode  = mode;

#if 0
    //应用层指定申请接收内存大小（申请即可，不用释放，内部会释放），默认不使用
    websockets_info->recv_buf_size	 = 30 * 1024;
    websockets_info->recv_buf		 = malloc(websockets_info->recv_buf_size);
#endif
}

static int websockets_client_init(struct websocket_struct *websockets_info, u8 *url, const char *origin_str)
{
    websockets_info->ip_or_url = url;
    websockets_info->origin_str = origin_str;
    websockets_info->recv_time_out = 1000;

    //应用层和库的版本检测，结构体不一样则返回出错
    int err = websockets_struct_check(sizeof(struct websocket_struct));
    if (err == FALSE) {
        return err;
    }
    return websockets_info->_init(websockets_info);
}

static int websockets_client_handshack(struct websocket_struct *websockets_info)
{
    return websockets_info->_handshack(websockets_info);
}

static int websockets_client_send_jl(struct websocket_struct *websockets_info, u8 *buf, int len, char type)
{
    int ret  = -1;
    os_mutex_pend(&__this->websockets_op_mutex, 0);
    if (websockets_info->websocket_valid == ESTABLISHED) {
        //SSL加密时一次发送数据不能超过16K，用户需要自己分包
        ret = websockets_info->_send(websockets_info, buf, len, type);
    }
    os_mutex_post(&__this->websockets_op_mutex);
    if (ret <= 0) {
        websockets_disconnect(websockets_info);
    }
    return ret;
}

static void websockets_client_exit(struct websocket_struct *websockets_info)
{
    websockets_info->_exit(websockets_info);
}

static int websockets_connect(void)
{
    int ret = 0;
    char mode = WEBSOCKET_MODE;
    struct websocket_struct *websockets_info = &__this->websockets_info;

    char src_buf[256] = {0};

    os_mutex_pend(&__this->websockets_op_mutex, 0);
    if (websockets_info->websocket_valid == ESTABLISHED) {
        os_mutex_post(&__this->websockets_op_mutex);
        return -1;
    }
    if (websockets_info->websocket_valid == INVALID_ESTABLISHED) {
        websockets_disconnect(websockets_info);
    }
    /* 1 . register */
    websockets_client_reg(websockets_info, mode);
    /* 2 . init */
    ret = websockets_client_init(websockets_info, WS_DEMO_URL, NULL);
    if (FALSE == ret) {
        printf("------Cilent websocket init error !!!\n");
        os_mutex_post(&__this->websockets_op_mutex);
        return -1;
    }
    /* 3 . hanshack */
    ret = websockets_client_handshack(websockets_info);
    if (FALSE == ret) {
        printf("------Handshake error !!!\n");
        os_mutex_post(&__this->websockets_op_mutex);
        return -1;
    }
    printf("------Handshake success\n");
    /* 4 . CreateThread */
    snprintf((char *)src_buf, sizeof(src_buf), "websocket_client_heart_%d", (u16)(random32(0) & 0xFFFF));
    thread_fork((const char *)src_buf, 19, 1024, 0,
                &websockets_info->ping_thread_id,
                websockets_info->_heart_thread,
                websockets_info);
    snprintf((char *)src_buf, sizeof(src_buf), "websocket_client_recv_%d", (u16)(random32(0) & 0xFFFF));
    thread_fork((const char *)src_buf, 18, 1024, 0,
                &websockets_info->recv_thread_id,
                websockets_info->_recv_thread,
                websockets_info);

    os_mutex_post(&__this->websockets_op_mutex);
    return 0;
}

static void websockets_disconnect(struct websocket_struct *websockets_info)
{
    int ret = 0;

    if (websockets_info->websocket_valid == NOT_ESTABLISHED) {
        return;
    }

    while (1) {
        printf("------websockets_disconnect enter\n");

        ret = os_mutex_pend(&__this->websockets_op_mutex, 10);
        if (ret == OS_NO_ERR) {
            if (websockets_info->websocket_valid != NOT_ESTABLISHED) {
                /* 6 . exit */
                websockets_info->websocket_valid = INVALID_ESTABLISHED;
                if (websockets_info->recv_thread_id) {
                    thread_kill(&websockets_info->recv_thread_id, KILL_WAIT);
                }
                if (websockets_info->ping_thread_id) {
                    thread_kill(&websockets_info->ping_thread_id, KILL_WAIT);
                }
                websockets_client_exit(websockets_info);
                websockets_info->websocket_valid = NOT_ESTABLISHED;
            }
            os_mutex_post(&__this->websockets_op_mutex);
        } else {
            if (websockets_info->websocket_valid != NOT_ESTABLISHED) {
                printf("\n %s %d\n", __func__, __LINE__);
                continue;
            }
        }
        break;
    }

    printf("------websockets_disconnect exit\n");
}

static void ws_task(void *priv)
{
    int err = 0;
    int msg[32];
    // websockets_connect();

    while (1) {
        err = os_taskq_pend("taskq", msg, ARRAY_SIZE(msg));
        if (err != OS_TASKQ || msg[0] != Q_USER) {
            continue;
        }
        switch (msg[1]) {
        case SH_WS_CONN:
            websockets_connect();
            // websockets_send_device_info(&__this->websockets_info);
        case SH_WS_SEND_AUDIO:
            if (__this->write_size - __this->send_size >= SEND_BUFFER_SIZE) {
                printf("------write size:%d, send size:%d\n", __this->write_size, __this->send_size);
                err = websockets_client_send_jl(&__this->websockets_info,
                    __this->mic_buf + __this->send_size,
                    SEND_BUFFER_SIZE,
                    WCT_BINDATA);
                if (err <= 0) {
                    close_audio_enc();
                    __this->write_size = 0;
                    os_taskq_flush();
                    if (wifi_get_sta_connect_state() == WIFI_STA_NETWORK_STACK_DHCP_SUCC) {
                        play_mix_file(SER_DISC_FILE);
                    }
                    // close_audio_dec();
                    // play_file(SER_DISC_FILE);
                }
                __this->send_size += SEND_BUFFER_SIZE;
            }
            break;
        case SH_WS_EXIT:
            websockets_disconnect(&__this->websockets_info);
            break;
        default:
            break;
        }
    }
    printf("\n %s  exit \n", __func__);
}

// 录音自定义文件写函数
static int recorder_vfs_fwrite(void *file, void *data, u32 len)
{
    size_t current_length = __this->write_size;

    // 检查缓冲区是否足够
    if (current_length + len >= REQ_BUFFER_SIZE) {
        printf("------Buffer overflow, response too large!\n");
        return 0; // 返回 0 以指示错误
    }

    // 直接将新数据写入缓冲区
    memcpy(__this->mic_buf  + current_length, data, len);
    printf("------write:start:%d, len:%d", __this->write_size, len);
    __this->write_size += len;
    if (__this->write_size - __this->send_size >= SEND_BUFFER_SIZE) {
        SH_OS_TASKQ_POST("ws_task", 1, SH_WS_SEND_AUDIO);
    }

    return len;
}

// 录音自定义文件关闭函数
static int recorder_vfs_fclose(void *file)
{
    return 0;
}

// 录音自定义虚拟文件函数集
static const struct audio_vfs_ops recorder_vfs_ops = {
    .fwrite = recorder_vfs_fwrite,
    .fclose = recorder_vfs_fclose,
};

// 开始录音
static int open_audio_enc()
{
    printf("----------open_audio_enc----------\n");
    union audio_req req = {0};

    __this->enc_flag = 1;
    __this->write_size = 0;
    __this->send_size = 0;

    req.enc.cmd = AUDIO_ENC_OPEN;
    req.enc.channel = __this->channel;
    req.enc.volume = __this->gain;
    req.enc.frame_size = 1600;
    req.enc.output_buf_len = req.enc.frame_size * 10;
    req.enc.sample_rate = __this->sample_rate;
    req.enc.format = __this->format;
    req.enc.sample_source = __this->sample_source;
    req.enc.msec = __this->enc_time_msec;
    req.enc.vfs_ops = &recorder_vfs_ops;
    req.enc.file = (FILE *)__this->mic_buf;
    if (!strcmp(req.enc.format, "aac")) {
        req.enc.bitrate = __this->sample_rate * 4;
        req.enc.no_header = 1;
    }
    if (__this->channel == 4) {
        req.enc.channel_bit_map = 0x0f;
    } else if (__this->channel == 2) {
        req.enc.channel_bit_map = BIT(CONFIG_AUDIO_ADC_CHANNEL_L) | BIT(CONFIG_AUDIO_ADC_CHANNEL_R);
    } else {
        req.enc.channel_bit_map = BIT(CONFIG_AUDIO_ADC_CHANNEL_L);
    }

    // 使能 VAD
    // req.enc.use_vad = 1;
    // req.enc.dns_enable = 1;
    // req.enc.vad_auto_refresh = 1;

    return server_request(__this->enc_server, AUDIO_REQ_ENC, &req);
}

// 停止录音
static int close_audio_enc()
{
    printf("----------close_audio_enc----------\n");
    union audio_req req = {0};

    if (!__this->enc_flag) {
        return 0;
    }
    __this->enc_flag = 0;

    if (__this->enc_server) {
        req.enc.cmd = AUDIO_ENC_CLOSE;
        server_request(__this->enc_server, AUDIO_REQ_ENC, &req);
    }

    return 0;
}

// 播放音频文件
static int play_file(const char* file_path)
{
    printf("----------local_dec_file:%s----------\n", file_path);
    int err = 0;
    union audio_req req = {0};

    FILE *file = NULL;
    file = __this->speaker_fp = fopen(file_path, "rb");

    if (!file) {
        printf("------file:%s open failed\n", file_path);
        return -1;
    }

    req.dec.cmd             = AUDIO_DEC_OPEN;
    req.dec.volume          = __this->volume;
    req.dec.output_buf_len  = 6 * 1024;
    req.dec.file            = file;
    req.dec.channel         = 0;
    req.dec.sample_rate     = 0;
    req.dec.priority        = 1;
    req.dec.sample_source   = __this->play_source;

    err = server_request(__this->dec_server, AUDIO_REQ_DEC, &req);
    if (err) {
        printf("------audio_dec_open: err = %d\n", err);
        fclose(file);
        __this->speaker_fp = NULL;
        return err;
    }

    req.dec.cmd = AUDIO_DEC_START;

    err = server_request(__this->dec_server, AUDIO_REQ_DEC, &req);
    if (err) {
        printf("------audio_dec_start: err = %d\n", err);
        fclose(file);
        __this->speaker_fp = NULL;
        return err;
    }
    __this->dec_server_status = AUDIO_DEC_START;

    return 0;
}

// 音频播放自定义虚拟文件读函数
static int play_vfs_fread(void *file, void *data, u32 len) {
    u32 rlen = 0;
    while (__this->dec_run_flag && __this->dec_ready_flag) {
        if (__this->recv_status && __this->recv_size - __this->play_size < RECV_BUFFER_SIZE) {
            len = __this->recv_size - __this->play_size;
        }

        rlen = cbuf_read(&__this->speaker_cbuf, data, len);
        if (rlen) {
            __this->play_size += rlen;

            if (__this->recv_status && __this->play_size >= __this->recv_size) {
                __this->dec_run_flag = 0;
                __this->dec_ready_flag = 0;
                printf("------res audio play complete!, play size:%d\n", __this->play_size);
            }
            break;
        }
        printf(">>>>>read pend......\n");
        os_sem_pend(&__this->r_sem, 0);
    }

    return ((__this->recv_status && __this->play_size >= __this->recv_size) ? 0 : len);
}

// 音频播放自定义虚拟文件获取长度函数
static int play_vfs_flen(void *priv)
{
    return RES_BUFFER_SIZE;
}

// 音频播放自定义虚拟文件定位函数
static int play_vfs_seek(void *priv, u32 offset, int orig)
{
    if (offset > 0) {
        __this->dec_ready_flag = 1; //解码器开始偏移数据后，再开始播放，避免音频播放开端吞字
    }
    return 0;
}

// 音频播放自定义虚拟文件函数集
static const struct audio_vfs_ops play_vfs_ops = {
    .fread  = play_vfs_fread,
    .flen   = play_vfs_flen,
    .fseek  = play_vfs_seek,
};

// 打开解码器
static int open_audio_dec(void* priv) {
    printf("----------open_audio_dec----------\n");
    int err = 0;
    union audio_req req = {0};

    req.dec.cmd             = AUDIO_DEC_OPEN;
    req.dec.volume          = __this->volume;
    req.dec.output_buf      = NULL;
    req.dec.output_buf_len  = 12 * 1024;
    req.dec.channel         = 0;
    req.dec.sample_rate     = 0;
    req.dec.priority        = 1;
    req.dec.sample_source   = __this->play_source;
    req.dec.dec_type 		= __this->format;
    req.dec.vfs_ops         = &play_vfs_ops;
    req.dec.file            = (FILE *)&__this->speaker_cbuf;

    //打开解码器
    err = server_request(__this->dec_server, AUDIO_REQ_DEC, &req);
    if (err) {
        printf("------audio_dec_open: err = %d\n", err);
        return err;
    }

    //开始解码
    req.dec.cmd = AUDIO_DEC_START;
    err = server_request(__this->dec_server, AUDIO_REQ_DEC, &req);
    if (err) {
        printf("------audio_dec_start: err = %d\n", err);
        return err;
    }
    __this->dec_server_status = AUDIO_DEC_START;

    return 0;
}

// 关闭解码器
static int close_audio_dec() {
    printf("----------close_audio_dec----------\n");
    __this->dec_run_flag = 0;
    __this->dec_ready_flag = 0;
    os_sem_post(&__this->r_sem);
    union audio_req req = {0};
    req.dec.cmd = AUDIO_DEC_STOP;

    if (__this->dec_server) {
        if (__this->dec_server_status != AUDIO_DEC_STOP) {
            server_request(__this->dec_server, AUDIO_REQ_DEC, &req);
            __this->dec_server_status = AUDIO_DEC_STOP;
        }
    }

    if (__this->speaker_fp) {
        fclose(__this->speaker_fp);
        __this->speaker_fp = NULL;
    }

    // 重置音频播放（接收）状态
    __this->recv_size = 0;
    __this->play_size = 0;
    __this->dec_status = 0;
    __this->recv_status = 0;
    cbuf_clear(&__this->speaker_cbuf);

    return 0;
}

// 混音解码器事件处理函数
static void mix_dec_server_event_handler(void *priv, int argc, int *argv)
{
    union audio_req r = {0};

    switch (argv[0]) {
    case AUDIO_SERVER_EVENT_ERR:
        puts("------mix_music: AUDIO_SERVER_EVENT_ERR\n");
    case AUDIO_SERVER_EVENT_END:
        puts("------mix_music: AUDIO_SERVER_EVENT_END\n");
        r.dec.cmd = AUDIO_DEC_STOP;
        server_request(priv, AUDIO_REQ_DEC, &r);
        server_close(priv);
        fclose((FILE *)argv[1]);
        break;
    default:
        break;
    }
}

// 混音解码器播放失败处理函数
static int play_mix_file_failed_handler(void *server, FILE *file, int err)
{
    if (server) {
        server_close(server);
    }
    if (file) {
        fclose(file);
    }

    printf("------play_mix_music_file: fail : %d\n", err);

    return err;
}

// 混音解码器播放函数
static int play_mix_file(const char *path)
{
    int err = 0;
    union audio_req req = {0};

#if !defined CONFIG_AUDIO_MIX_ENABLE
    return 0;
#endif

    printf("------play_mix_file : %s\n", path);

    FILE *file = fopen(path, "r");
    if (!file) {
        return -ENOENT;
    }

    void *dec_server = server_open("audio_server", "dec");
    if (!dec_server) {
        return play_mix_file_failed_handler(dec_server, file, err);
    }
    server_register_event_handler_to_task(dec_server, dec_server, mix_dec_server_event_handler, "app_core");

    req.dec.cmd             = AUDIO_DEC_OPEN;
    req.dec.volume          = __this->volume;
    req.dec.output_buf_len  = 6 * 1024;
    req.dec.file            = file;
    req.dec.sample_source   = __this->play_source;

    err = server_request(dec_server, AUDIO_REQ_DEC, &req);
    if (err) {
        return play_mix_file_failed_handler(dec_server, file, err);
    }

    req.dec.cmd = AUDIO_DEC_START;

    err = server_request(dec_server, AUDIO_REQ_DEC, &req);
    if (err) {
        return play_mix_file_failed_handler(dec_server, file, err);
    }

    puts("------play_mix_music_file: suss\n");

    return 0;
}

// 网络音乐播放
//网络解码需要的数据访问句柄
static const struct audio_vfs_ops net_audio_dec_vfs_ops = {
    .fread = net_download_read,
    .fseek = net_download_seek,
    .flen  = net_download_get_file_len,
};

//检查音频需要的格式检查数据头部是否下载缓冲完成
static int __net_download_ready(void *p)
{
    __this->download_ready = net_download_check_ready(__this->net_file);
    if (__this->download_ready) {
        return 1;
    }
    return 0;
}

//停止播放
static int net_music_dec_stop(void)
{
    union audio_req r = {0};
    union ai_req req = {0};

    if (!__this->net_file) {
        return 0;
    }

    printf("net_music_dec_stop\n");

    net_download_buf_inactive(__this->net_file);

    if (__this->wait_download) {
        /*
         * 歌曲还未开始播放，删除wait
         */
        /* sys_timer_del(__this->wait_download); */
        wait_completion_del(__this->wait_download);
        __this->wait_download = 0;
    } else {
        r.dec.cmd = AUDIO_DEC_STOP;
        server_request(__this->dec_server, AUDIO_REQ_DEC, &r);

        int argv[2];
        argv[0] = AUDIO_SERVER_EVENT_END;
        argv[1] = (int)__this->net_file;
        server_event_handler_del(__this->dec_server, 2, argv);
    }

    extern int lwip_canceladdrinfo(void);
    lwip_canceladdrinfo();
    //释放网络下载资源
    net_download_close(__this->net_file);
    __this->net_file = NULL;

    return 0;
}

//播放结束
static int net_music_dec_end(void)
{
    printf("net_music_dec_end\n");

    net_music_dec_stop();

    __this->is_net_music = 0;

    return 0;
}

static char* get_net_music_media_type(void)
{
    const char *format_str = "format$";
    size_t format_len = strlen(format_str);
    const char *url = __this->net_music_url; // 假设__this已正确定义且net_music_url已初始化

    if (!url) {
        printf("URL is not initialized.\n");
        return NULL;
    }

    // 查找format$的位置
    const char *start = strstr(url, format_str);
    if (!start) {
        return NULL;
    }

    // 跳过"format$"
    start += format_len;

    // 查找&符号或空格结束位置
    const char *end = strchr(start, '&');
    if (!end) {
        end = strchr(start, ' ');
        if (!end) {
            end = start + strlen(start); // 处理到字符串末尾的情况
        }
    }

    size_t len = end - start;
    char *result = (char *)malloc(len + 1); // 分配足够空间并包含空字符
    if (!result) {
        printf("Memory allocation failed.\n");
        return NULL;
    }

    memcpy(result, start, len);
    result[len] = '\0'; // 确保字符串以空字符结尾

    return result; // 返回动态分配的内存，调用者需负责释放
}

// 混音解码器播放失败处理函数
static int __net_music_dec_file_failed_handler(void *file)
{
    printf("play_net_music_faild\n");
    union audio_req req = {0};

    net_download_buf_inactive(file);

    req.dec.cmd = AUDIO_DEC_STOP;
    server_request(__this->dec_server, AUDIO_REQ_DEC, &req);

    net_download_close(file);
    __this->net_file = NULL;

    return -1;
}

//数据缓冲已完成，开始解码
static int __net_music_dec_file(void *file)
{
    int err = 0;
    union ai_req r = {0};
    union audio_req req = {0};

    __this->wait_download = 0;

    if (__this->download_ready < 0) {
        /* 网络下载失败 */
        return __net_music_dec_file_failed_handler(file);
    }

    //获取网络资源的格式
    char *media_type = get_net_music_media_type();
    if (!media_type) {
        req.dec.dec_type = "mp3";
    } else {
        req.dec.dec_type = media_type;
    }
    printf("url_file_type: %s\n", req.dec.dec_type);

    net_download_set_read_timeout(file, 5000);

    req.dec.cmd             = AUDIO_DEC_OPEN;
    req.dec.volume          = __this->volume;
    req.dec.output_buf_len  = 6 * 1024;
    req.dec.file            = (FILE *)file;
    req.dec.channel         = 0;
    req.dec.sample_rate     = 0;
    req.dec.priority        = 1;
    req.dec.vfs_ops         = &net_audio_dec_vfs_ops;
    req.dec.sample_source   = CONFIG_AUDIO_DEC_PLAY_SOURCE;

    err = server_request(__this->dec_server, AUDIO_REQ_DEC, &req);
    if (err) {
        if (media_type) {
            free(media_type);
        }
        return __net_music_dec_file_failed_handler(file);
    }

    net_download_set_read_timeout(file, 0);

    req.dec.cmd = AUDIO_DEC_START;

    server_request(__this->dec_server, AUDIO_REQ_DEC, &req);

    net_download_set_pp(file, 0);
    if (media_type) {
        free(media_type);
    }

    return 0;
}

// 启动网络音乐播放
static int net_music_dec_file(const char *url)
{
    int err = 0;
    struct net_download_parm parm = {0};

    // close_audio_dec();

    if (!url) {
        return -1;
    }

    printf("net_download_open\n");

    parm.url                = url;
    //网络缓冲buf大小
#ifdef CONFIG_NO_SDRAM_ENABLE
    parm.cbuf_size          = 150 * 1024;
#else
    parm.cbuf_size          = 500 * 1024;
#endif
    //设置网络下载超时
    parm.timeout_millsec    = 10000;
    parm.seek_threshold     = 1024 * 200;	//用户可适当调整
    /* parm.seek_low_range     = __this->dec_bp.fptr;    //恢复断点时设置网络的开始下载地址 */

    err = net_download_open(&__this->net_file, &parm);
    if (err) {
        printf("net_download_open: err = %d\n", err);
        return err;
    }

    __this->is_net_music = 1;

    /*异步等待网络下载ready，防止网络阻塞导致app_core卡住 */
    // __this->wait_download = wait_completion_add_to_task("app_core", __net_download_ready,
    //     (int (*)(void *))__net_music_dec_file, __this->net_file, NULL);
    __this->wait_download = wait_completion(__net_download_ready,
        (int (*)(void *))__net_music_dec_file, __this->net_file, NULL);

    return 0;
}

// 编码器事件处理handler
static void enc_server_event_handler(void *priv, int argc, int *argv)
{
    switch (argv[0]) {
    case AUDIO_SERVER_EVENT_ERR:
    case AUDIO_SERVER_EVENT_END:
        printf("------mic record end! \n");
        close_audio_enc();
        play_mix_file(FAIL_FILE);
        break;
    case AUDIO_SERVER_EVENT_SPEAK_START:
        printf("------speak start ! \n");
        break;
    case AUDIO_SERVER_EVENT_SPEAK_STOP:
        printf("------speak stop ! \n");
        break;
    default:
        break;
    }
}

// 解码器事件处理handler
static void dec_server_event_handler(void *priv, int argc, int *argv)
{
    switch (argv[0]) {
    case AUDIO_SERVER_EVENT_ERR:
    case AUDIO_SERVER_EVENT_END:
        printf("----------audio dec end! \n");
        if (__this->is_net_music) {
            net_music_dec_end();
        } else {
            close_audio_dec();
        }
        if (__this->has_net_music) {
            __this->has_net_music = 0;
            net_music_dec_file(__this->net_music_url);
        }
        break;
    default:
        break;
    }
}

// 模式初始化
static int ws_interact_mode_init(void)
{
    printf("------ws_interact mode init\n");
    //extern void get_fw_version;
    //get_fw_version

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

#ifdef CONFIG_STORE_VOLUME
    if (syscfg_read(CFG_MUSIC_VOL, &__this->volume, sizeof(__this->volume)) < 0 ||
        __this->volume < MIN_VOLUME_VALUE || __this->volume > MAX_VOLUME_VALUE) {
        __this->volume = INIT_VOLUME_VALUE;
    }
#else
    __this->volume = INIT_VOLUME_VALUE;
#endif
    if (__this->volume < 0 || __this->volume > MAX_VOLUME_VALUE) {
        __this->volume = INIT_VOLUME_VALUE;
    }

    // __this->volume = INIT_VOLUME_VALUE;
    __this->gain = CONFIG_AUDIO_ADC_GAIN;
    __this->channel = CONFIG_AUDIO_RECORDER_CHANNEL;
    __this->format = CONFIG_AUDIO_RECORDER_SAVE_FORMAT;
    __this->sample_source = "mic";
    __this->play_source = CONFIG_AUDIO_DEC_PLAY_SOURCE;
    __this->sample_rate = CONFIG_AUDIO_RECORDER_SAMPLERATE;
    __this->enc_time_msec = CONFIG_AUDIO_RECORDER_DURATION;

    __this->enc_server = server_open("audio_server", "enc");
    server_register_event_handler_to_task(__this->enc_server, NULL, enc_server_event_handler, "app_core");

    __this->dec_server = server_open("audio_server", "dec");
    server_register_event_handler_to_task(__this->dec_server, NULL, dec_server_event_handler, "app_core");
    __this->dec_server_status = AUDIO_DEC_STOP;

    __this->mic_buf = malloc(REQ_BUFFER_SIZE);
    if (__this->mic_buf == NULL) {
        return -1;
    }
    __this->net_music_url = malloc(512);
    if (__this->net_music_url == NULL) {
        return -1;
    }

    __this->speaker_buf = malloc(RES_BUFFER_SIZE);
    if (__this->speaker_buf == NULL) {
        return -1;
    }
    cbuf_init(&__this->speaker_cbuf, __this->speaker_buf, RES_BUFFER_SIZE);
    os_sem_create(&__this->r_sem, 0);

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

    return 0;
}

// 模式退出
static void ws_interact_mode_exit(void)
{
    printf("------ws_interact mode exit\n");
    close_audio_enc();
    close_audio_dec();
    server_close(__this->dec_server);
    __this->dec_server = NULL;

    server_close(__this->enc_server);
    __this->enc_server = NULL;

    if (__this->mic_buf) {
        free(__this->mic_buf);
        __this->mic_buf = NULL;
    }

    if (__this->net_music_url) {
        free(__this->net_music_url);
        __this->net_music_url = NULL;
    }

    if (__this->speaker_buf) {
        free(__this->speaker_buf);
        __this->speaker_buf = NULL;
    }
    SH_OS_TASKQ_POST("ws_task", 1, SH_WS_EXIT);
}
#define HTTP_DEMO_URL  "http://ai.agent.kaywang.cn:8988/api/v1/aiagent/generateAIAgentCall"
#define HTTP_DEMO_DATA "{\"app_id\": \"apppibr915pu75m\", \"config\" : \"{\\\"llm\\\" : \\\"LLMRacing\\\", \\\"llm_token\\\" : \\\"no\\\", \\\"rtc_ac\\\": \\\"pcmu\\\", \\\"lang\\\" : \\\"zh\\\"}\", \"quick_start\": true}"

#define LOG_HTTP_HEAD_OPTION_BAIDU        \
    "POST /api/v1/aiagent/generateAIAgentCall HTTP/1.1\r\n"\
    "Host: ai.agent.kaywang.cn\r\n"\
    "Connection: close\r\n"\
    "Content-length: 155\r\n"
#define HTTP_POST_TEST
static void http_test_task_test(void* priv) {
    int ret = 0;
    http_body_obj http_body_buf;
    httpcli_ctx* ctx = (httpcli_ctx*)calloc(1, sizeof(httpcli_ctx));
    if (!ctx) {
        printf("calloc faile\n");
        return;
    }

    memset(&http_body_buf, 0x0, sizeof(http_body_obj));

    http_body_buf.recv_len = 0;
    http_body_buf.buf_len = 4 * 1024;
    http_body_buf.buf_count = 1;
    http_body_buf.p = (char*)malloc(http_body_buf.buf_len * http_body_buf.buf_count);
    if (!http_body_buf.p) {
        free(ctx);
        return;
    }

    ctx->url = HTTP_DEMO_URL;
    ctx->timeout_millsec = 5000;
    ctx->priv = &http_body_buf;
    ctx->connection = "close";

#if (defined HTTP_POST_TEST)
    printf("http post test start\n\n");
    ctx->data_format = "application/json";
    ctx->post_data = HTTP_DEMO_DATA;
    ctx->data_len = strlen(HTTP_DEMO_DATA);
    /* ctx->user_http_header = LOG_HTTP_HEAD_OPTION;	//添加该参数, 则自定义申请头部内容 */
    ret = httpcli_post(ctx);
#elif (defined HTTP_GET_TEST)
    printf("http get test start\n\n");
    ret = httpcli_get(ctx);
#elif (defined HTTP_PUT_TEST)
    printf("http put test start\n\n");
    ret = httpcli_put(ctx);
#endif

    printf("TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTask is http");

    //构造函数，并且传递给ai_agent模块
    struct AgentEngineParams* pAgentEngineParams = zalloc(sizeof(struct AgentEngineParams));


    if (ret != HERROR_OK) {
        printf("http client test faile\n");
    }
    else {
        if (http_body_buf.recv_len > 0) {
            printf("\nReceive %d Bytes from (%s)\n", http_body_buf.recv_len, HTTP_DEMO_URL);
            printf("%s\n", http_body_buf.p);
        }
        printf("http client test succfully\n");
    }

    //TODO:此处解析json 太复杂了，内部解析吧
    snprintf(pAgentEngineParams->remote_params, sizeof(pAgentEngineParams->remote_params), http_body_buf.p);
    snprintf(pAgentEngineParams->appid, sizeof(pAgentEngineParams->appid), "apppibr915pu75m");
    //关闭连接
    httpcli_close(ctx);

    if (http_body_buf.p) {
        free(http_body_buf.p);
        http_body_buf.p = NULL;
    }

    if (ctx) {
        free(ctx);
        ctx = NULL;
    }


    //传递给aiagent
    pAgentEngineParams->enable_local_agent = false; //外部创建智能体
    //解析json,获取agent的服务器得参数
    //下发构造
    extern void baidu_chat_agent_demo_open(void*);
    ret = thread_fork(" baidu_chat_agent_demo", 21, 1024 * 16, 128, NULL, (void*)baidu_chat_agent_demo_open, pAgentEngineParams);
    printf("ret = %d\n", ret);
}
// 按键事件
static int ws_interact_key_click(struct key_event *key)
{
    int ret = true;
    int ready = 0;
    enum wifi_sta_connect_state state;
    printf("ws_interact---> key value: %d <--- KEY_OK:%d , _this->enc_flag:%d __this->is_net_music:%d ",key->value, KEY_OK, __this->enc_flag, __this->is_net_music);
    switch (key->value) {
    case KEY_OK:
        // low_power_all_group_force_sleep(10000000);
        if (__this->enc_flag) {
            // 当前正在录音，忽略按键功能
        } else if (__this->dec_run_flag || __this->is_net_music) {
            // 当前正在播放，发送停止生成消息，取消播放
            printf("ws_interact---> key value:dddddddddddddddddddddddddddddddddddddddddd");
            __this->recv_status = 1;
            if (__this->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();

                //  printf("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBrt begin...");
                //  if (thread_fork("http_test_task_test", 10, 1024 * 10, 0, NULL, http_test_task_test, NULL) != OS_NO_ERR) {
                //      printf("thread fork fail\n");
                //  }
            } else {
                close_audio_dec();
                play_file(NET_UNVALID_FILE);
            }
            printf("ws_interact---> key value:pppppppppppppppppppppppppppppppppppppppppp");

        }

        break;
    default:
        ret = false;
        break;
    }

    return ret;
}

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();
        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 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:
        printf("  [KEY_EVENT_CLICK]  \n");
        return ws_interact_key_click(key);
    case KEY_EVENT_LONG:
        printf("  [KEY_EVENT_LONG]  \n");
        // return ws_interact_key_click(key);
        set_dec_volume(VOLUME_STEP);
    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\n");
            play_mix_file(NET_CFG_FAIL_FILE);
            ble_cfg_net_result_notify(event->event);
            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;
            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;
            __this->recv_status = 1;
            if (__this->net_connected && !is_in_config_network_state() && !__this->reconnecting) {
                play_mix_file(NET_DISC_FILE);
            }
            __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 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)
{
    switch (state) {
    case APP_STA_CREATE:
        break;
    case APP_STA_START:
        ws_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 	= "ws_interact",
    .ops 	= &ws_interact_ops,
    .state  = APP_STA_DESTROY,
};
