/**
 * @file hal_url_player.c
 * @brief HAL HTTP URL 流式播放实现。
 *
 * URL 播放相关操作统一派发到 app_core 执行。
 * audio_server 事件也绑定到 app_core，便于统一管理播放状态。
 */

#include "hal_url_player.h"
#include "hal_log.h"
#include "system/includes.h"
#include "system/wait.h"
#include "system/timer.h"
#include "server/audio_server.h"
#include "network_download/net_download.h"
#include "os/os_api.h"
#include <stdlib.h>
#include <string.h>

#define TAG  "HAL_UPLY"

#define URL_TASK_NAME           "app_core"
#define URL_NET_BUF_SIZE        (500 * 1024)  /* 网络播放缓冲区大小 */
#define URL_NET_TIMEOUT_MS      10000
#define URL_NET_SEEK_THRESHOLD  (200 * 1024)
#define URL_DEC_OUTPUT_BUF_LEN  (6 * 1024)
#define URL_DEC_READ_TIMEOUT_MS 5000
#define URL_MAX_LEN             512   /* 与协议层 PLAY_AUDIO 上限一致 */

typedef struct {
    void                     *dec_server;
    void                     *net_file;
    u16                       wait_download;
    int                       download_ready;
    hal_url_player_done_cb_t  done_cb;
    void                     *done_ctx;
    volatile bool             active;
    volatile bool             paused;
    u8                        volume;

    /* 待播放 URL，由接口写入并在 app_core 中处理。 */
    char                      pending_url[URL_MAX_LEN];
} hal_url_player_impl_t;

/* net_download 数据访问回调注入到 audio_server */
static const struct audio_vfs_ops s_url_vfs_ops = {
    .fread = net_download_read,
    .fseek = net_download_seek,
    .flen  = net_download_get_file_len,
};

static void url_event_handler(void *priv, int argc, int *argv);

static int url_check_ready(void *p)
{
    hal_url_player_impl_t *impl = (hal_url_player_impl_t *)p;
    impl->download_ready = net_download_check_ready(impl->net_file);
    return (impl->download_ready != 0) ? 1 : 0;
}

static int url_dec_release(hal_url_player_impl_t *impl)
{
    if (impl->net_file) {
        net_download_buf_inactive(impl->net_file);

        if (impl->wait_download) {
            wait_completion_del(impl->wait_download);
            impl->wait_download = 0;
        } else if (impl->dec_server) {
            union audio_req r = {0};
            r.dec.cmd = AUDIO_DEC_STOP;
            server_request(impl->dec_server, AUDIO_REQ_DEC, &r);
        }

        extern int lwip_canceladdrinfo(void);
        lwip_canceladdrinfo();

        net_download_close(impl->net_file);
        impl->net_file = NULL;
    }

    /* 释放播放资源，便于其他播放模块使用 */
    if (impl->dec_server) {
        server_close(impl->dec_server);
        impl->dec_server = NULL;
    }

    impl->paused = false;
    impl->active = false;
    return 0;
}

static int url_dec_start(void *priv)
{
    hal_url_player_impl_t *impl = (hal_url_player_impl_t *)priv;
    impl->wait_download = 0;

    if (impl->download_ready < 0 || !impl->net_file) {
        BD_LOGE(TAG, "download fail: %d", impl->download_ready);
        url_dec_release(impl);
        if (impl->done_cb) {
            impl->done_cb(impl->done_ctx);
        }
        return -1;
    }

    net_download_set_read_timeout(impl->net_file, URL_DEC_READ_TIMEOUT_MS);

    union audio_req req = {0};
    req.dec.cmd            = AUDIO_DEC_OPEN;
    req.dec.volume         = impl->volume;
    req.dec.output_buf_len = URL_DEC_OUTPUT_BUF_LEN;
    req.dec.file           = (FILE *)impl->net_file;
    req.dec.vfs_ops        = &s_url_vfs_ops;
    req.dec.sample_source  = "dac";

    int err = server_request(impl->dec_server, AUDIO_REQ_DEC, &req);
    if (err) {
        BD_LOGE(TAG, "dec open fail: %d", err);
        url_dec_release(impl);
        if (impl->done_cb) {
            impl->done_cb(impl->done_ctx);
        }
        return -1;
    }

    net_download_set_read_timeout(impl->net_file, 0);

    req.dec.cmd = AUDIO_DEC_START;
    server_request(impl->dec_server, AUDIO_REQ_DEC, &req);

    net_download_set_pp(impl->net_file, 0);
    BD_LOGI(TAG, "url playback started");
    return 0;
}

/* 在 app_core 中启动 URL 播放 */
static void url_play_in_app_core(void *priv)
{
    hal_url_player_impl_t *impl = (hal_url_player_impl_t *)priv;
    if (!impl) {
        return;
    }

    /* 新播放开始前先停止当前播放 */
    url_dec_release(impl);

    /* 按需打开播放服务 */
    impl->dec_server = server_open("audio_server", "dec");
    if (!impl->dec_server) {
        BD_LOGE(TAG, "open dec server fail");
        if (impl->done_cb) {
            impl->done_cb(impl->done_ctx);
        }
        return;
    }
    server_register_event_handler_to_task(impl->dec_server, impl,
                                          url_event_handler, URL_TASK_NAME);

    struct net_download_parm parm = {0};
    parm.url             = impl->pending_url;
    parm.cbuf_size       = URL_NET_BUF_SIZE;
    parm.timeout_millsec = URL_NET_TIMEOUT_MS;
    parm.seek_threshold  = URL_NET_SEEK_THRESHOLD;

    int err = net_download_open(&impl->net_file, &parm);
    if (err) {
        BD_LOGE(TAG, "net_download_open fail: %d", err);
        url_dec_release(impl);
        if (impl->done_cb) {
            impl->done_cb(impl->done_ctx);
        }
        return;
    }

    impl->active = true;
    impl->paused = false;

    /* 等待网络数据就绪后开始播放 */
    impl->wait_download = wait_completion(url_check_ready,
                                          (int (*)(void *))url_dec_start,
                                          impl, NULL);
    if (!impl->wait_download) {
        BD_LOGE(TAG, "wait_completion fail");
        url_dec_release(impl);
        if (impl->done_cb) {
            impl->done_cb(impl->done_ctx);
        }
        return;
    }

    BD_LOGI(TAG, "url playing: %.80s", impl->pending_url);
}

static void url_stop_in_app_core(void *priv)
{
    hal_url_player_impl_t *impl = (hal_url_player_impl_t *)priv;
    if (impl) {
        url_dec_release(impl);
    }
}

static void url_pause_in_app_core(void *priv)
{
    hal_url_player_impl_t *impl = (hal_url_player_impl_t *)priv;
    if (impl && impl->net_file && !impl->paused) {
        net_download_set_pp(impl->net_file, 1);
        impl->paused = true;
    }
}

static void url_resume_in_app_core(void *priv)
{
    hal_url_player_impl_t *impl = (hal_url_player_impl_t *)priv;
    if (impl && impl->net_file && impl->paused) {
        net_download_set_pp(impl->net_file, 0);
        impl->paused = false;
    }
}

static void url_event_handler(void *priv, int argc, int *argv)
{
    hal_url_player_impl_t *impl = (hal_url_player_impl_t *)priv;
    if (!impl) {
        return;
    }

    int event = argv[0];
    if (event == AUDIO_SERVER_EVENT_END || event == AUDIO_SERVER_EVENT_ERR) {
        BD_LOGI(TAG, "url playback end (evt=%d)", event);
        url_dec_release(impl);
        if (impl->done_cb) {
            impl->done_cb(impl->done_ctx);
        }
    }
}

hal_url_player_handle_t hal_url_player_create(void)
{
    hal_url_player_impl_t *impl = (hal_url_player_impl_t *)zalloc(sizeof(*impl));
    if (!impl) {
        return NULL;
    }
    impl->volume = 30;
    /* 播放服务在开始播放时按需打开 */
    return (hal_url_player_handle_t)impl;
}

int hal_url_player_play(hal_url_player_handle_t handle,
                        const char *url,
                        hal_url_player_done_cb_t done_cb,
                        void *user_ctx)
{
    if (!handle || !url) {
        return -1;
    }
    hal_url_player_impl_t *impl = (hal_url_player_impl_t *)handle;

    size_t n = strnlen(url, URL_MAX_LEN - 1);
    memcpy(impl->pending_url, url, n);
    impl->pending_url[n] = '\0';

    impl->done_cb  = done_cb;
    impl->done_ctx = user_ctx;

    u16 id = sys_timeout_add_to_task(URL_TASK_NAME, impl,
                                     url_play_in_app_core, 0);
    BD_LOGI(TAG, "post play to app_core, id=%u", id);
    return id ? 0 : -1;
}

int hal_url_player_stop(hal_url_player_handle_t handle)
{
    if (!handle) {
        return -1;
    }
    u16 id = sys_timeout_add_to_task(URL_TASK_NAME, handle,
                                     url_stop_in_app_core, 0);
    return id ? 0 : -1;
}

int hal_url_player_pause(hal_url_player_handle_t handle)
{
    if (!handle) {
        return -1;
    }
    u16 id = sys_timeout_add_to_task(URL_TASK_NAME, handle,
                                     url_pause_in_app_core, 0);
    return id ? 0 : -1;
}

int hal_url_player_resume(hal_url_player_handle_t handle)
{
    if (!handle) {
        return -1;
    }
    u16 id = sys_timeout_add_to_task(URL_TASK_NAME, handle,
                                     url_resume_in_app_core, 0);
    return id ? 0 : -1;
}

int hal_url_player_set_volume(hal_url_player_handle_t handle, uint8_t volume)
{
    if (!handle) {
        return -1;
    }
    hal_url_player_impl_t *impl = (hal_url_player_impl_t *)handle;
    impl->volume = volume;

    if (impl->active && impl->dec_server) {
        union audio_req req = {0};
        req.dec.cmd    = AUDIO_DEC_SET_VOLUME;
        req.dec.volume = volume;
        server_request(impl->dec_server, AUDIO_REQ_DEC, &req);
    }
    return 0;
}

bool hal_url_player_is_active(hal_url_player_handle_t handle)
{
    if (!handle) {
        return false;
    }
    return ((hal_url_player_impl_t *)handle)->active;
}

void hal_url_player_destroy(hal_url_player_handle_t handle)
{
    if (!handle) {
        return;
    }
    hal_url_player_impl_t *impl = (hal_url_player_impl_t *)handle;

    /* 释放播放资源 */
    url_dec_release(impl);
    free(impl);
}
