/*
 * Copyright (c) 2026 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "AudioVividPlaybackManager.h"
#include "AudioVividWrapper.h"
#include <cstring>
#include <chrono>

AudioVividPlaybackManager::AudioVividPlaybackManager()
{}

AudioVividPlaybackManager::~AudioVividPlaybackManager()
{
    Release();
}

int32_t AudioVividPlaybackManager::Initialize()
{
    int32_t ret = pcmReader_.Open(
        "/data/storage/el2/base/haps/entry/files/resfile/2ch_2obj_48k_24bit.pcm", SAMPLE_RATE, PCM_CHANNEL_COUNT, 24);
    if (ret != 0) {
        AVCODEC_SAMPLE_LOGE("Failed to open PCM file");
        return -1;
    }
    ret = encoder_.Create();
    if (ret != 0) {
        AVCODEC_SAMPLE_LOGE("Failed to create encoder");
        return -1;
    }
    ret = encoder_.Config(SAMPLE_RATE, PCM_CHANNEL_COUNT, CHANNEL_LAYOUT, BITRATE);
    if (ret != 0) {
        AVCODEC_SAMPLE_LOGE("Failed to config encoder");
        return -1;
    }
    ret = decoder_.Create();
    if (ret != 0) {
        AVCODEC_SAMPLE_LOGE("Failed to create decoder");
        return -1;
    }
    ret = decoder_.Config(SAMPLE_RATE, PCM_CHANNEL_COUNT, CHANNEL_LAYOUT);
    if (ret != 0) {
        AVCODEC_SAMPLE_LOGE("Failed to config decoder");
        return -1;
    }
    ret = renderer_.Create(SAMPLE_RATE, PCM_CHANNEL_COUNT, CHANNEL_LAYOUT);
    if (ret != 0) {
        AVCODEC_SAMPLE_LOGE("Failed to create renderer");
        return -1;
    }
    renderer_.SetPlaybackManager(this);
    AVCODEC_SAMPLE_LOGI("AudioVividPlaybackManager initialized successfully");
    return 0;
}

int32_t AudioVividPlaybackManager::Start()
{
    if (isRunning_.load()) {
        AVCODEC_SAMPLE_LOGW("Playback is already running");
        return 0;
    }
    shouldStop_.store(false);
    presentationTimeUs_.store(0);
    GenerateInitialMetadata();
    int32_t ret = renderer_.Start();
    if (ret != 0) {
        AVCODEC_SAMPLE_LOGE("Failed to start renderer");
        return -1;
    }
    ret = encoder_.Start();
    if (ret != 0) {
        AVCODEC_SAMPLE_LOGE("Failed to start encoder");
        return -1;
    }
    ret = decoder_.Start();
    if (ret != 0) {
        AVCODEC_SAMPLE_LOGE("Failed to start decoder");
        return -1;
    }
    encoderInputThread_ = std::thread(&AudioVividPlaybackManager::EncoderInputThread, this);
    encoderOutputThread_ = std::thread(&AudioVividPlaybackManager::EncoderOutputThread, this);
    decoderOutputThread_ = std::thread(&AudioVividPlaybackManager::DecoderOutputThread, this);
    isRunning_.store(true);
    AVCODEC_SAMPLE_LOGI("AudioVividPlaybackManager started successfully");
    return 0;
}

int32_t AudioVividPlaybackManager::Stop()
{
    if (!isRunning_.load()) {
        AVCODEC_SAMPLE_LOGW("Playback is not running");
        return 0;
    }
    shouldStop_.store(true);
    encoder_.GetContext()->inputCond.notify_all();
    encoder_.GetContext()->outputCond.notify_all();
    decoder_.GetContext()->inputCond.notify_all();
    decoder_.GetContext()->outputCond.notify_all();
    decodedQueueCond_.notify_all();
    if (encoderInputThread_.joinable()) {
        encoderInputThread_.join();
    }
    if (encoderOutputThread_.joinable()) {
        encoderOutputThread_.join();
    }
    if (decoderOutputThread_.joinable()) {
        decoderOutputThread_.join();
    }
    decoder_.Stop();
    encoder_.Stop();
    renderer_.Stop();
    isRunning_.store(false);
    AVCODEC_SAMPLE_LOGI("AudioVividPlaybackManager stopped successfully");
    return 0;
}

int32_t AudioVividPlaybackManager::Release()
{
    Stop();
    encoder_.Release();
    decoder_.Release();
    renderer_.Release();
    pcmReader_.Close();
    if (currentMetadata_) {
        delete[] currentMetadata_;
        currentMetadata_ = nullptr;
    }
    currentMetadataSize_ = 0;
    std::lock_guard<std::mutex> lock(decodedQueueMutex_);
    while (!decodedDataQueue_.empty()) {
        AudioVividDecoderData *data = decodedDataQueue_.front();
        decodedDataQueue_.pop();
        if (data) {
            if (data->pcmData) {
                delete[] data->pcmData;
            }
            if (data->metadata) {
                delete[] data->metadata;
            }
            delete data;
        }
    }
    AVCODEC_SAMPLE_LOGI("AudioVividPlaybackManager released successfully");
    return 0;
}

void AudioVividPlaybackManager::GenerateInitialMetadata()
{
    vividWrapper_.Initialize();
    vividWrapper_.UpdateObjectPosition(0, 1.0f, 0.0f, 0.0f);
    vividWrapper_.UpdateObjectPosition(1, -1.0f, 0.0f, 0.0f);
    for (int i = 0; i < 2; i++) { // 2:示例代码为2个对象
        vividWrapper_.UpdateObjectGain(i, 1.0f);
    }
    std::vector<uint8_t> metadata = vividWrapper_.GetMetadata(true);
    {
        std::lock_guard<std::mutex> lock(metadataMutex_);
        if (currentMetadata_) {
            delete[] currentMetadata_;
        }
        currentMetadata_ = new uint8_t[metadata.size()];
        memcpy(currentMetadata_, metadata.data(), metadata.size());
        currentMetadataSize_ = metadata.size();
    }
    encoder_.UpdateMetadata(currentMetadata_, currentMetadataSize_);
}

void AudioVividPlaybackManager::UpdateMetadata(uint8_t *metadata, int32_t metadataSize)
{
    std::lock_guard<std::mutex> lock(metadataMutex_);
    if (currentMetadata_) {
        delete[] currentMetadata_;
    }
    if (metadataSize > 10485760) { // 10485760:10MB 异常过大的输入大小
        return;
    }
    currentMetadata_ = new uint8_t[metadataSize];
    memcpy(currentMetadata_, metadata, metadataSize);
    currentMetadataSize_ = metadataSize;
    encoder_.UpdateMetadata(metadata, metadataSize);
}

int32_t AudioVividPlaybackManager::GetDecodedDataToRender(
    uint8_t **pcmData, int32_t *pcmSize, uint8_t **metadata, int32_t *metadataSize)
{
    std::unique_lock<std::mutex> lock(decodedQueueMutex_);
    decodedQueueCond_.wait(lock, [this] { return !decodedDataQueue_.empty() || shouldStop_.load(); });
    if (shouldStop_.load() && decodedDataQueue_.empty()) {
        return -1;
    }
    AudioVividDecoderData *data = decodedDataQueue_.front();
    decodedDataQueue_.pop();
    *pcmData = data->pcmData;
    *pcmSize = data->pcmSize;
    *metadata = data->metadata;
    *metadataSize = data->metadataSize;
    data->pcmData = nullptr;
    data->metadata = nullptr;
    delete data;
    return 0;
}

void AudioVividPlaybackManager::EncoderInputThread()
{
    uint8_t *pcmBuffer = new uint8_t[BYTES_PER_PCM_FRAME];
    uint8_t *encoderBuffer = new uint8_t[BYTES_PER_FRAME];
    while (!shouldStop_.load()) {
        size_t queueSize = 0;
        {
            std::lock_guard<std::mutex> lock(decodedQueueMutex_);
            queueSize = decodedDataQueue_.size();
        }
        if (queueSize >= MAX_DECODED_QUEUE_SIZE) {
            std::this_thread::sleep_for(std::chrono::milliseconds(20)); // 等待20ms再读取数据,未消耗的buffer较多
            continue;
        }
        int32_t bytesRead = pcmReader_.Read(pcmBuffer, BYTES_PER_PCM_FRAME);
        if (bytesRead <= 0) {
            if (pcmReader_.IsEOF()) {
                pcmReader_.Reset();
                AVCODEC_SAMPLE_LOGI("PCM file looped, restarting from beginning");
            }
            continue;
        }
        memset(encoderBuffer, 0, BYTES_PER_FRAME);
        memcpy(encoderBuffer, pcmBuffer, bytesRead);
        int64_t pts = presentationTimeUs_.fetch_add(FRAME_SIZE * 1000000 / SAMPLE_RATE); // 1000000:1s转为us
        uint8_t *metadata = nullptr;
        int32_t metadataSize = 0;
        {
            std::lock_guard<std::mutex> lock(metadataMutex_);
            if (currentMetadata_ && currentMetadataSize_ > 0) {
                metadata = currentMetadata_;
                metadataSize = currentMetadataSize_;
            }
        }
        int32_t ret = encoder_.PushInputBuffer(encoderBuffer, BYTES_PER_FRAME, metadata, metadataSize, pts);
        if (ret != 0) {
            AVCODEC_SAMPLE_LOGE("Failed to push input buffer to encoder");
        }
    }
    delete[] pcmBuffer;
    delete[] encoderBuffer;
    AVCODEC_SAMPLE_LOGI("EncoderInputThread exited");
}

void AudioVividPlaybackManager::EncoderOutputThread()
{
    while (!shouldStop_.load()) {
        AudioVividEncoderOutputData *outputData = encoder_.GetOutputBuffer();
        if (outputData == nullptr) {
            std::this_thread::sleep_for(std::chrono::milliseconds(10)); // 等10ms输入
            continue;
        }
        if (outputData->eos) {
            delete outputData;
            break;
        }
        int32_t ret = decoder_.PushInputBuffer(outputData->encodedData, outputData->encodedSize);
        if (ret != 0) {
            AVCODEC_SAMPLE_LOGE("Failed to push input buffer to decoder");
        }
        delete outputData;
        encoder_.FreeOutputBuffer();
    }
    AVCODEC_SAMPLE_LOGI("EncoderOutputThread exited");
}

void AudioVividPlaybackManager::DecoderOutputThread()
{
    while (!shouldStop_.load()) {
        AudioVividDecoderData *outputData = decoder_.GetOutputBuffer();
        if (outputData == nullptr) {
            std::this_thread::sleep_for(std::chrono::milliseconds(10)); // 10:示例代码等待解码数据输出10ms
            continue;
        }
        if (outputData->pcmData && outputData->pcmSize > 0) {
            std::lock_guard<std::mutex> lock(decodedQueueMutex_);
            decodedDataQueue_.push(outputData);
            decodedQueueCond_.notify_one();
        } else {
            if (outputData->pcmData) {
                delete[] outputData->pcmData;
            }
            if (outputData->metadata) {
                delete[] outputData->metadata;
            }
            delete outputData;
        }
        decoder_.FreeOutputBuffer();
    }
    AVCODEC_SAMPLE_LOGI("DecoderOutputThread exited");
}