/**
 * @file audio_codec.c
 * @brief 音频编解码实现（raw16k 直通 / G.722）
 */

#include "audio/audio_codec.h"
#include "g722_enc_dec.h"
#include "hal_log.h"
#include <stdlib.h>
#include <string.h>

#define TAG "CODEC"

/* G.722 固定使用 64kbps 宽带模式 */
#define G722_RATE_64K   64000
#define G722_OPTIONS    0

typedef enum {
    CODEC_PASSTHROUGH = 0,   /* raw16k/raw/pcm：不转换 */
    CODEC_G722,
} codec_type_t;

struct audio_codec {
    codec_type_t     type;
    G722EncoderState enc;    /* 上行 */
    G722DecoderState dec;    /* 下行 */
};

static codec_type_t parse_type(const char *name)
{
    if (name && strcmp(name, "g722") == 0) {
        return CODEC_G722;
    }
    return CODEC_PASSTHROUGH;
}

audio_codec_t *audio_codec_create(const char *name)
{
    audio_codec_t *codec = (audio_codec_t *)calloc(1, sizeof(*codec));
    if (!codec) {
        return NULL;
    }

    codec->type = parse_type(name);
    if (codec->type == CODEC_G722) {
        WebRtc_g722_encode_init(&codec->enc, G722_RATE_64K, G722_OPTIONS);
        WebRtc_g722_decode_init(&codec->dec, G722_RATE_64K, G722_OPTIONS);
        BD_LOGI(TAG, "codec = g722");
    } else {
        BD_LOGI(TAG, "codec = passthrough(%s)", name ? name : "raw16k");
    }
    return codec;
}

int audio_codec_encode(audio_codec_t *codec, const void *pcm, int pcm_bytes,
                       void *out, int out_cap)
{
    if (!codec || !pcm || !out || pcm_bytes <= 0) {
        return -1;
    }

    if (codec->type == CODEC_G722) {
        int samples = pcm_bytes / 2;          /* 16bit 采样数 */
        if (samples / 2 > out_cap) {          /* 64kbps: 每 2 采样输出 1 字节 */
            return -1;
        }
        size_t n = WebRtc_g722_encode(&codec->enc, (uint8_t *)out,
                                      (const int16_t *)pcm, (size_t)samples);
        return (int)n;
    }

    /* 直通 */
    if (pcm_bytes > out_cap) {
        return -1;
    }
    memcpy(out, pcm, (size_t)pcm_bytes);
    return pcm_bytes;
}

int audio_codec_decode(audio_codec_t *codec, const void *in, int in_bytes,
                       void *pcm_out, int out_cap)
{
    if (!codec || !in || !pcm_out || in_bytes <= 0) {
        return -1;
    }

    if (codec->type == CODEC_G722) {
        if (in_bytes * 4 > out_cap) {         /* 每字节 2 采样，每采样 2 字节 */
            return -1;
        }
        size_t samples = WebRtc_g722_decode(&codec->dec, (int16_t *)pcm_out,
                                            (const uint8_t *)in, (size_t)in_bytes);
        return (int)(samples * 2);            /* 转为字节数 */
    }

    /* 直通 */
    if (in_bytes > out_cap) {
        return -1;
    }
    memcpy(pcm_out, in, (size_t)in_bytes);
    return in_bytes;
}

bool audio_codec_is_passthrough(const audio_codec_t *codec)
{
    return (!codec) || (codec->type == CODEC_PASSTHROUGH);
}

void audio_codec_reset(audio_codec_t *codec)
{
    if (!codec) {
        return;
    }
    if (codec->type == CODEC_G722) {
        WebRtc_g722_encode_init(&codec->enc, G722_RATE_64K, G722_OPTIONS);
        WebRtc_g722_decode_init(&codec->dec, G722_RATE_64K, G722_OPTIONS);
    }
}

void audio_codec_destroy(audio_codec_t *codec)
{
    if (codec) {
        free(codec);
    }
}
