#ifndef __RKAUDIO_H__
#define __RKAUDIO_H__

#include <chrono>
#include <functional>
#include <mutex>
#include <thread>
#include <vector>

namespace RkAudio {

class Format {
public:
    enum Endian {
        BigEndian,
        LittleEndian,
    };

    enum SampleType {
        Unknown,
        SignedInt16,
        SignedInt,
        Float,
    };
    SampleType sampleType = SignedInt16;
    Endian byteOrder = LittleEndian;
    uint32_t sampleRate = 16000;
    uint32_t channels = 1;
    uint32_t period = 16;
};

class Frame {
public:
    uint8_t *data = nullptr;
    int32_t byteSize = 0;
    int32_t frameSize = 0;
    std::chrono::system_clock::time_point timestamp;
};

class Input {
public:
    using ReadCallback = std::function<void(const Frame &)>;
    Input();
    ~Input();
    void setDataCallback(const ReadCallback &callback);
    bool open(const Format &format,bool enableVqe);
    void stop();

protected:
    void run();

private:
    int32_t m_channel = -1;
    bool m_exit = false;
    std::thread m_thread;
    ReadCallback m_callback;
    Format m_format;
};

class Output {
public:
    Output();
    ~Output();
    bool open(uint32_t sampleSize, uint32_t sampleRate, uint32_t channels, uint32_t period,bool enableVqe);
    void close();
    void write(const uint8_t *data, uint32_t byteSize);

private:
    int32_t m_channel = -1;
};

} // namespace RkAudio

/**
 * @brief 目前系统取录音数据,只能64ms。而opus编码需要20ms一周期
 *
 */
class PcmStreamBuffer {
public:
    PcmStreamBuffer(uint32_t sampleRate, uint32_t channels, RkAudio::Format::SampleType sampleType, uint32_t popDuration,
                    uint32_t capacity);
    bool push(const RkAudio::Frame &frame);
    std::chrono::milliseconds availableDuration() const;
    uint32_t availableByteSize() const;
    const RkAudio::Frame *pop();

private:
    uint32_t m_sampleRate;
    uint32_t m_channels;
    uint32_t m_pointByteSize = 0;

    std::vector<uint8_t> m_buffer;
    uint32_t m_capacity;
    uint32_t m_head = 0;
    uint32_t m_tail = 0;
    bool m_full = false;

    RkAudio::Frame m_popFrame;
    std::vector<uint8_t> m_popBuffer;
    std::mutex m_mutex;
};

#endif // __RKAUDIO_H__