/**
 * @file hal_local_player.c
 * @brief HAL 本地文件播放实现（JieLi 平台）
 */

#include "hal_local_player.h"
#include "hal_log.h"
#include "system/includes.h"
#include "server/audio_server.h"
#include "os/os_api.h"
#include <stdlib.h>
#include <string.h>

#define TAG  "HAL_LPLY"

typedef struct {
    void                       *dec_server;
    hal_local_player_done_cb_t  done_cb;
    void                       *done_ctx;
    volatile bool               playing;
    u8                          volume;
} hal_local_player_impl_t;

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

    /* 播放结束事件 */
    int event = argv[0];
    if (event == AUDIO_SERVER_EVENT_END || event == AUDIO_SERVER_EVENT_ERR) {
        impl->playing = false;
        if (impl->done_cb) {
            impl->done_cb(impl->done_ctx);
        }
    }
}

hal_local_player_handle_t hal_local_player_create(void)
{
    hal_local_player_impl_t *impl = (hal_local_player_impl_t *)zalloc(sizeof(hal_local_player_impl_t));
    if (!impl) {
        return NULL;
    }

    impl->dec_server = server_open("audio_server", "dec");
    if (!impl->dec_server) {
        BD_LOGE(TAG, "open dec server fail");
        free(impl);
        return NULL;
    }

    impl->playing = false;
    impl->volume = 30;

    /* 注册事件回调 */
    server_register_event_handler(impl->dec_server, impl, local_player_event_handler);

    return (hal_local_player_handle_t)impl;
}

int hal_local_player_play(hal_local_player_handle_t handle,
                          const char *file_path,
                          hal_local_player_done_cb_t done_cb,
                          void *user_ctx)
{
    if (!handle || !file_path) {
        return -1;
    }
    hal_local_player_impl_t *impl = (hal_local_player_impl_t *)handle;

    /* 如果正在播放，先停止 */
    if (impl->playing) {
        hal_local_player_stop(handle);
    }

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

    union audio_req req = {0};
    req.dec.cmd = AUDIO_DEC_OPEN;
    req.dec.volume = impl->volume;
    req.dec.output_buf_len = 4 * 1024;
    req.dec.file = (FILE *)fopen(file_path, "r");
    req.dec.dec_type = NULL;  /* auto-detect from file */

    int ret = server_request(impl->dec_server, AUDIO_REQ_DEC, &req);
    if (ret) {
        BD_LOGE(TAG, "dec open fail: %d, file=%s", ret, file_path);
        return -1;
    }

    req.dec.cmd = AUDIO_DEC_START;
    ret = server_request(impl->dec_server, AUDIO_REQ_DEC, &req);
    if (ret) {
        BD_LOGE(TAG, "dec start fail: %d", ret);
        req.dec.cmd = AUDIO_DEC_STOP;
        server_request(impl->dec_server, AUDIO_REQ_DEC, &req);
        return -1;
    }

    impl->playing = true;
    BD_LOGI(TAG, "playing: %s", file_path);
    return 0;
}

int hal_local_player_stop(hal_local_player_handle_t handle)
{
    if (!handle) {
        return -1;
    }
    hal_local_player_impl_t *impl = (hal_local_player_impl_t *)handle;

    if (!impl->playing) {
        return 0;
    }

    union audio_req req = {0};
    req.dec.cmd = AUDIO_DEC_STOP;
    server_request(impl->dec_server, AUDIO_REQ_DEC, &req);

    impl->playing = false;
    return 0;
}

int hal_local_player_set_volume(hal_local_player_handle_t handle, uint8_t volume)
{
    if (!handle) {
        return -1;
    }
    hal_local_player_impl_t *impl = (hal_local_player_impl_t *)handle;
    impl->volume = volume;

    if (impl->playing && 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;
}

void hal_local_player_destroy(hal_local_player_handle_t handle)
{
    if (!handle) {
        return;
    }
    hal_local_player_impl_t *impl = (hal_local_player_impl_t *)handle;

    hal_local_player_stop(handle);

    if (impl->dec_server) {
        server_close(impl->dec_server);
    }

    free(impl);
}
