/*
 * 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.
 */
#ifndef AUDIO_VIVID_ENCODER_H
#define AUDIO_VIVID_ENCODER_H
#include <multimedia/player_framework/native_avcodec_audiocodec.h>
#include "AudioConfig.h"
#include "AudioLog.h"
#include <queue>
#include <mutex>
#include <condition_variable>

struct AudioVividEncoderInputData {
    uint8_t *pcmData = nullptr;
    int32_t pcmSize = 0;
    uint8_t *metadata = nullptr;
    int32_t metadataSize = 0;
    int64_t presentationTimeUs = 0;
};

struct AudioVividEncoderOutputData {
    uint8_t *encodedData = nullptr;
    int32_t encodedSize = 0;
    int64_t presentationTimeUs = 0;
    bool eos = false;
};

struct AudioVividEncoderContext {
    std::mutex inputMutex;
    std::condition_variable inputCond;
    std::queue<uint32_t> inputBufferIndices;
    std::queue<OH_AVBuffer *> inputBufferQueue;
    std::mutex outputMutex;
    std::condition_variable outputCond;
    std::queue<AudioVividEncoderOutputData> outputQueue;
    bool eos = false;
    int32_t errorCode = 0;
};

class AudioVividEncoder {
public:
    AudioVividEncoder() = default;
    ~AudioVividEncoder();
    int32_t Create();
    int32_t Config(int32_t sampleRate, int32_t channelCount, int64_t channelLayout, int32_t bitrate);
    int32_t Start();
    int32_t PushInputBuffer(
        uint8_t *pcmData, int32_t pcmSize, uint8_t *metadata, int32_t metadataSize, int64_t presentationTimeUs);
    AudioVividEncoderOutputData *GetOutputBuffer();
    void FreeOutputBuffer();
    int32_t NotifyEndOfStream();
    int32_t Stop();
    int32_t Release();
    AudioVividEncoderContext *GetContext()
    {
        return &context_;
    }
    void UpdateMetadata(uint8_t *metadata, int32_t metadataSize);

private:
    int32_t SetCallback();
    int32_t Configure();
    void AttachMetadataToBuffer(OH_AVBuffer *buffer, uint8_t *metadata, int32_t metadataSize);
    OH_AVCodec *encoder_ = nullptr;
    AudioVividEncoderContext context_;
    int32_t sampleRate_ = AudioConfig::SAMPLE_RATE;
    int32_t channelCount_ = AudioConfig::CHANNEL_COUNT;
    int64_t channelLayout_ = AudioConfig::CHANNEL_LAYOUT;
    int32_t bitrate_ = AudioConfig::BITRATE;
    uint8_t *currentMetadata_ = nullptr;
    int32_t currentMetadataSize_ = 0;
    std::mutex metadataMutex_;
};

#endif