#ifndef AVPLAYER2_AUDIO_PLAY_THREAD_H
#define AVPLAYER2_AUDIO_PLAY_THREAD_H

#pragma once

#include <QAudio>
#include <QAudioDeviceInfo>
#include <QAudioOutput>
#include <QDebug>
#include <QFile>
#include <QIODevice>
#include <QQueue>
#include <QWaitCondition>

#include <memory>
#include <atomic>

#include "packets_sync.h"
#include "ThreadBase.h"

#define BUFFER_LEN 8192 // 1024

typedef struct AudioData
{
    uint16_t len = 0;
    char buffer[BUFFER_LEN] = {0};
} AudioData;

typedef struct AudioFrameFmt
{
    uint sample_rate;
    uint sample_fmt; // AV_SAMPLE_FMT_S16
    uint channel;
    int byte_order;  // QAudioFormat::LittleEndian;
    int sample_type; // QAudioFormat::SignedInt
} AudioFrameFmt;

class AudioPlayThread : public ThreadBase
{
public:
    explicit AudioPlayThread(VideoState* pState = nullptr);
    virtual ~AudioPlayThread();

public:
    void print_device() const;
    bool init_device(int sample_rate = 8000, int channel = 1, AVSampleFormat sample_fmt = AV_SAMPLE_FMT_S16, float default_vol = 0.8);
    void stop_device();
    void play_file(const QString& file);
    void play_buf(const uint8_t* buf, int datasize);
    bool init_resample_param(AVCodecContext* pAudio, AVSampleFormat sample_fmt, VideoState* is);
    void final_resample_param();
    float get_device_volume() const;
    void set_device_volume(float volume);
    void send_visual_open(bool bSend = true) { m_bSendToVisual = bSend; };

    void setOnUpdatePlayTime(std::function<void()> cb) { m_onUpdatePlayTime = std::move(cb); }
    void setOnDataVisualReady(std::function<void(const AudioData&)> cb) { m_onDataVisualReady = std::move(cb); }

protected:
    void run() override;

private:
    int audio_decode_frame(VideoState* is);

private:
    typedef struct Audio_Resample
    {
        struct SwrContext* swrCtx{nullptr};
    } Audio_Resample;

private:
    QAudioOutput* m_pOutput;
    QIODevice* m_audioDevice{nullptr};
    VideoState* m_pState{nullptr};
    Audio_Resample m_audioResample;
    bool m_bSendToVisual{false};
    std::function<void()> m_onUpdatePlayTime;
    std::function<void(const AudioData&)> m_onDataVisualReady;
};

#endif // AVPLAYER2_AUDIO_PLAY_THREAD_H
