#include "server/audio_server.h"
#include "server/server_core.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 "fs/fs.h"
#include <time.h>
#include <curl/curl.h>

#include "app_config.h"
#include "storage_device.h"

// #define CONFIG_STORE_VOLUME
#define VOLUME_STEP         5
#define GAIN_STEP           5
#define MIN_VOLUME_VALUE	5
#define MAX_VOLUME_VALUE	100
#define INIT_VOLUME_VALUE   70

#define FAIL_FILE           CONFIG_VOICE_PROMPT_FILE_PATH"AsrEmpty.mp3"
#define NET_FAIL_FILE       CONFIG_VOICE_PROMPT_FILE_PATH"NetCfgFail.mp3"
// #define NULL_FILE           CONFIG_VOICE_PROMPT_FILE_PATH"001.mp3"
#define HOST_NAME           "180.101.51.191"
#define HTTP_DEMO_URL       "http://"HOST_NAME"/process_audio/"
#define REQ_BUFFER_SIZE     1024 * 1024
#define RES_BUFFER_SIZE     1024 * 1024
#define RECV_BUFFER_SIZE    (512)

struct 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;                 // 音频已采集大小

    // 音频播放
    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：完成
};

static struct interact_hdl interact_handler;

#define __this (&interact_handler)

// 停止录音
static int recorder_close()
{
    printf("----------recorder close----------\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 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;

    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;

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

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

// 播放音频文件
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;
    }

    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;
    }

    return 0;
}

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

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

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

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

    return 0;
}

// 回调函数，用于接收服务器返回的语音
size_t curl_write_cb(void *ptr, size_t size, size_t nmemb, void *userdata) {
    size_t realsize = size * nmemb;
    char *buffer = (char *)userdata;

    // 找到写入的位置
    u32 wlen = 0;
    while (realsize > 0) {
        size_t to_write = (realsize > RECV_BUFFER_SIZE) ? RECV_BUFFER_SIZE : realsize;
        wlen = cbuf_write(&__this->speaker_cbuf, ptr, to_write);
        if (wlen) {
            os_sem_post(&__this->r_sem);
            __this->recv_size += to_write;
            //音频下载成功，或缓存成功，打开解码器，开始播放
            if (__this->recv_size >= 2 * 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;
            }
        }
        // 更新指针和剩余数据大小
        ptr = (char *)ptr + to_write; // 移动指针
        realsize -= to_write;          // 减少剩余大小
    }
    
    return size * nmemb; // 返回实际处理的字节数
}

// 调用远程接口
static int remote_process() {
    printf("----------------do remote process");
    CURL *curl = NULL;
    CURLcode res = CURLE_OK;
    curl_mime *mime = NULL;
    curl_mimepart *part = NULL;
    __this->recv_size = 0;
    
    curl_global_init(CURL_GLOBAL_ALL);
    curl = curl_easy_init();
    if (!curl) {
        curl_global_cleanup();
        return -1;
    }

    __this->dec_run_flag = 1;
    printf("-------req buffer size: %d", __this->write_size);

    int ret = 0;
    // 设置URL
    curl_easy_setopt(curl, CURLOPT_URL, HTTP_DEMO_URL);
    // 允许重定向
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
    // 设置超时时间
    curl_easy_setopt(curl, CURLOPT_TIMEOUT, 60L); // 总超时30秒
    curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10L); // 连接超时10秒

        // 创建 MIME 数据
    mime = curl_mime_init(curl);
    part = curl_mime_addpart(mime);
    curl_mime_name(part, "input_file");
    curl_mime_filename(part, "req.mp3");
    curl_mime_type(part, "audio/mpeg");  // 设置MIME类型
    curl_mime_data(part, __this->mic_buf, __this->write_size);  // 从缓冲区发送数据

    curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
    
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curl_write_cb);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, __this->speaker_buf);

    // 执行请求
    res = curl_easy_perform(curl);

    // 检查请求结果
    if(res != CURLE_OK) {
        printf("curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
        ret = -3;
    } else {
        long http_code = 0;
        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
        if(http_code != 200) {
            printf("Upload failed with HTTP status code: %ld\n", http_code);
            __this->recv_size = 0;
            ret = -4;
        } else {
            printf("Request succeeded.\n");
        }
    }
    // 清理
    curl_mime_free(mime); // 释放 MIME 数据
    curl_easy_cleanup(curl);
    curl_global_cleanup();
    if (__this->recv_size <= 2 * 1024) {
        // close_audio_dec();
        play_file(FAIL_FILE);
    } else {
        // 音频接收完成
        __this->recv_status = 1;
    }
    return ret;
}

// 编码器事件处理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");
        recorder_close();
        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");
        close_audio_dec();
        break;
    default:
        break;
    }
}

// 模式初始化
static int interact_mode_init(void)
{
    printf("interact mode init\n");

    memset(__this, 0, sizeof(struct interact_hdl));
    __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->mic_buf = malloc(REQ_BUFFER_SIZE);
    if (__this->mic_buf == 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);

    return 0;
}

// 模式退出
static void interact_mode_exit(void)
{
    printf("interact mode exit\n");
    recorder_close();
    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->speaker_buf) {
        free(__this->speaker_buf);
        __this->speaker_buf = NULL;
    }
}

// 按键事件
static int interact_key_click(struct key_event *key)
{
    int ret = true;
    int ready = 0;
    enum wifi_sta_connect_state state;
    printf("interact---> key value: %d <---",key->value);
    switch (key->value) {
    case KEY_OK:
        if (__this->enc_flag) {
            // 当前正在录音，结束录音，调用远程接口
            recorder_close();
            if (thread_fork("remote_process", 15, 8 * 1024, 0, NULL, remote_process, NULL) != OS_NO_ERR) {
                printf("thread fork fail\n");
            }
        } else {
            // 当前空闲或正在进行音频播放，结束播放，开启录音
            state = wifi_get_sta_connect_state();
            printf("**************wifi_get_sta_connect_state: %d ********************\n", state);
            if (WIFI_STA_NETWORK_STACK_DHCP_SUCC == state) {
                close_audio_dec();
                printf("----------------do mic audio record");
                open_audio_enc();
            } else {
                close_audio_dec();
                play_file(NET_FAIL_FILE);
            }
        }
        break;
    default:
        ret = false;
        break;
    }

    return ret;
}

static int interact_key_event_handler(struct key_event *key)
{
    switch (key->action) {
    case KEY_EVENT_CLICK:
        printf("************interact_key_click***************\n");
        return interact_key_click(key);
    default:
        break;
    }

    return true;
}

static int interact_event_handler(struct application *app, struct sys_event *event)
{
    switch (event->type) {
    case SYS_KEY_EVENT:
        return interact_key_event_handler((struct key_event *)event->payload);
    default:
        return false;
    }
}

static int interact_state_machine(struct application *app, enum app_state state, struct intent *it)
{
    switch (state) {
    case APP_STA_CREATE:
        break;
    case APP_STA_START:
        interact_mode_init();
        break;
    case APP_STA_PAUSE:
        break;
    case APP_STA_RESUME:
        break;
    case APP_STA_STOP:
        interact_mode_exit();
        break;
    case APP_STA_DESTROY:
        break;
    }

    return 0;
}

static const struct application_operation interact_ops = {
    .state_machine  = interact_state_machine,
    .event_handler 	= interact_event_handler,
};

REGISTER_APPLICATION(interact) = {
    .name 	= "interact",
    .ops 	= &interact_ops,
    .state  = APP_STA_DESTROY,
};
