#include "audio_qt_capturer.h"
#include "qaudio.h"

#include <QAudioDeviceInfo>
#include <QDebug>

#include <qendian.h>

AudioInfo::AudioInfo(const QAudioFormat& format)
    : m_format(format)
{
    switch (m_format.sampleSize()) {
    case 8:
        switch (m_format.sampleType()) {
        case QAudioFormat::UnSignedInt:
            m_maxAmplitude = 255;
            break;
        case QAudioFormat::SignedInt:
            m_maxAmplitude = 127;
            break;
        default:
            break;
        }
        break;
    case 16:
        switch (m_format.sampleType()) {
        case QAudioFormat::UnSignedInt:
            m_maxAmplitude = 65535;
            break;
        case QAudioFormat::SignedInt:
            m_maxAmplitude = 32767;
            break;
        default:
            break;
        }
        break;

    case 32:
        switch (m_format.sampleType()) {
        case QAudioFormat::UnSignedInt:
            m_maxAmplitude = 0xffffffff;
            break;
        case QAudioFormat::SignedInt:
            m_maxAmplitude = 0x7fffffff;
            break;
        case QAudioFormat::Float:
            m_maxAmplitude = 0x7fffffff; // Kind of
        default:
            break;
        }
        break;

    default:
        break;
    }
}

void AudioInfo::start()
{
    open(QIODevice::WriteOnly);
}

void AudioInfo::stop()
{
    close();
}

qint64 AudioInfo::readData(char* data, qint64 maxlen)
{
    Q_UNUSED(data)
    Q_UNUSED(maxlen)

    return 0;
}

qint64 AudioInfo::writeData(const char* data, qint64 len)
{
    if (m_maxAmplitude) {
        Q_ASSERT(m_format.sampleSize() % 8 == 0);
        const int channelBytes = m_format.sampleSize() / 8;
        const int sampleBytes = m_format.channelCount() * channelBytes;
        Q_ASSERT(len % sampleBytes == 0);
        const int numSamples = len / sampleBytes;

        quint32 maxValue = 0;
        const unsigned char* ptr = reinterpret_cast<const unsigned char*>(data);

        for (int i = 0; i < numSamples; ++i) {
            for (int j = 0; j < m_format.channelCount(); ++j) {
                quint32 value = 0;

                if (m_format.sampleSize() == 8
                    && m_format.sampleType() == QAudioFormat::UnSignedInt) {
                    value = *reinterpret_cast<const quint8*>(ptr);
                } else if (m_format.sampleSize() == 8
                           && m_format.sampleType() == QAudioFormat::SignedInt) {
                    value = qAbs(*reinterpret_cast<const qint8*>(ptr));
                } else if (m_format.sampleSize() == 16
                           && m_format.sampleType() == QAudioFormat::UnSignedInt) {
                    if (m_format.byteOrder() == QAudioFormat::LittleEndian)
                        value = qFromLittleEndian<quint16>(ptr);
                    else
                        value = qFromBigEndian<quint16>(ptr);
                } else if (m_format.sampleSize() == 16
                           && m_format.sampleType() == QAudioFormat::SignedInt) {
                    if (m_format.byteOrder() == QAudioFormat::LittleEndian)
                        value = qAbs(qFromLittleEndian<qint16>(ptr));
                    else
                        value = qAbs(qFromBigEndian<qint16>(ptr));
                } else if (m_format.sampleSize() == 32
                           && m_format.sampleType() == QAudioFormat::UnSignedInt) {
                    if (m_format.byteOrder() == QAudioFormat::LittleEndian)
                        value = qFromLittleEndian<quint32>(ptr);
                    else
                        value = qFromBigEndian<quint32>(ptr);
                } else if (m_format.sampleSize() == 32
                           && m_format.sampleType() == QAudioFormat::SignedInt) {
                    if (m_format.byteOrder() == QAudioFormat::LittleEndian)
                        value = qAbs(qFromLittleEndian<qint32>(ptr));
                    else
                        value = qAbs(qFromBigEndian<qint32>(ptr));
                } else if (m_format.sampleSize() == 32
                           && m_format.sampleType() == QAudioFormat::Float) {
                    value = qAbs(*reinterpret_cast<const float*>(ptr) * 0x7fffffff); // assumes 0-1.0
                }

                maxValue = qMax(value, maxValue);
                ptr += channelBytes;
            }
        }

        maxValue = qMin(maxValue, m_maxAmplitude);
        m_level = qreal(maxValue) / m_maxAmplitude;
    }

    emit update();
    return len;
}

QtAudioCapturer::QtAudioCapturer(QObject* parent)
    : QObject(parent)
    , m_deviceType(Microphone)
    , m_isRunning(false)
{
    // 初始化缓冲区
    m_buffer.open(QIODevice::ReadWrite);

    // 设置处理定时器
    connect(&m_processTimer, &QTimer::timeout, this, &QtAudioCapturer::processAudioData);
}

QtAudioCapturer::~QtAudioCapturer()
{
    Stop();
}

bool QtAudioCapturer::Init(Type deviceType)
{
    m_deviceType = deviceType;
    if (m_deviceType == Microphone) {
        return initMicrophone();
    } else {
        return initSpeaker();
    }
}

bool QtAudioCapturer::Start()
{
    if (m_isRunning) {
        qDebug() << "QtAudioCapturer::Start - 已经在运行中";
        return true;
    }

    if (!m_audioInput && m_deviceType == Microphone) {
        qWarning() << "QtAudioCapturer::Start - 音频输入未初始化";
        return false;
    }

    qDebug() << "QtAudioCapturer::Start - 开始捕获音频，设备类型:"
             << (m_deviceType == Microphone ? "麦克风" : "扬声器");

    if (m_deviceType == Microphone && m_audioInput) {
        m_buffer.buffer().clear();
        m_buffer.seek(0);
        m_audioInput->start(&m_buffer); // 使用push模式，将数据写入m_buffer

        qDebug() << "QtAudioCapturer::Start - QAudioInput state:" << m_audioInput->state();
        qDebug() << "QtAudioCapturer::Start - QAudioInput error:" << m_audioInput->error();

        if (m_audioInput->error() != QAudio::NoError) {
            qWarning() << "QtAudioCapturer::Start - 启动音频输入失败, error:"
                     << m_audioInput->error();
            return false;
        }

        m_processTimer.start(20); // 启动定时器来处理m_buffer中的数据
    }
    m_isRunning = true;
    return true;
}

void QtAudioCapturer::Stop()
{
    if (!m_isRunning) {
        return;
    }

    m_processTimer.stop();

    if (m_audioInput) {
        if (m_audioInput->state() != QAudio::StoppedState) {
            m_audioInput->stop();
        }
    }

    m_buffer.buffer().clear();
    m_buffer.seek(0);
    m_dataBuffer.clear();
    m_isRunning = false;
}

const AudioFormat& QtAudioCapturer::GetFormat() const
{
    return m_audioFormat;
}

int QtAudioCapturer::readAudioData(char* buf, int maxLen)
{
    QMutexLocker locker(&m_mutex);
    int toRead = qMin(maxLen, m_dataBuffer.size());
    // qDebug() << "[readAudioData] toRead=" << toRead
    //          << ", m_dataBuffer.size()=" << m_dataBuffer.size();
    if (toRead > 0) {
        memcpy(buf, m_dataBuffer.constData(), toRead);
        m_dataBuffer.remove(0, toRead);
    }
    return toRead;
}

void QtAudioCapturer::processAudioData()
{
    int bufSize = m_buffer.size();
    // qDebug() << "[processAudioData] m_buffer.size()=" << bufSize << ", m_dataBuffer.size()=" << m_dataBuffer.size();
    // 定时器触发，将m_buffer中的数据转移到m_dataBuffer，以供readAudioData消费
    if (bufSize > 0) {
        QMutexLocker locker(&m_mutex);
        m_dataBuffer.append(m_buffer.buffer());
        m_buffer.buffer().clear();
        m_buffer.seek(0);
    }
}

bool QtAudioCapturer::initMicrophone()
{
    qDebug() << "QtAudioCapturer::initMicrophone - 默认输入设备: "
             << QAudioDeviceInfo::defaultInputDevice().deviceName();
    QList<QAudioDeviceInfo> availableDevices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
    qDebug() << "QtAudioCapturer::initMicrophone - 可用的音频输入设备:";
    for (const QAudioDeviceInfo& deviceInfo : availableDevices) {
        qDebug() << "  " << deviceInfo.deviceName();
    }

    AudioFormat defaultFormat = IAudioCapturer::GetDefaultFormat();
    QAudioFormat format;
    format.setSampleRate(defaultFormat.sampleRate);
    format.setChannelCount(defaultFormat.channels);
    format.setSampleSize(defaultFormat.bitsPerSample);
    format.setCodec("audio/pcm");
    format.setByteOrder(QAudioFormat::LittleEndian);
    format.setSampleType(QAudioFormat::SignedInt);

    QAudioDeviceInfo deviceInfo = QAudioDeviceInfo::defaultInputDevice();
    if (!deviceInfo.isFormatSupported(format)) {
        qWarning() << "QtAudioCapturer::initMicrophone - 默认格式不支持，尝试使用最接近的格式";
        format = deviceInfo.nearestFormat(format);
    }

    m_qtAudioFormat = format;
    m_audioFormat = AudioFormat(m_qtAudioFormat.sampleRate(), m_qtAudioFormat.channelCount(),
                                m_qtAudioFormat.sampleSize());

    // 创建音频输入
    m_audioInput = std::make_unique<QAudioInput>(deviceInfo, m_qtAudioFormat, this);

    m_audioInfo.reset(new AudioInfo(m_qtAudioFormat));
    m_audioInfo->start();
    qDebug() << "QtAudioCapturer::initMicrophone - 音频输入创建成功，格式:"
             << "采样率=" << m_qtAudioFormat.sampleRate()
             << "通道数=" << m_qtAudioFormat.channelCount()
             << "采样大小=" << m_qtAudioFormat.sampleSize();

    return true;
}

bool QtAudioCapturer::initSpeaker()
{
    return false;
}

float QtAudioCapturer::calculateVolume(const QByteArray& data)
{
    // 计算音频数据的音量级别
    if (data.isEmpty()) {
        return 0.0f;
    }

    // 假设数据是16位有符号整数
    const int16_t* samples = reinterpret_cast<const int16_t*>(data.constData());
    int sampleCount = data.size() / sizeof(int16_t);

    // 计算平均绝对值
    float sum = 0.0f;
    for (int i = 0; i < sampleCount; ++i) {
        sum += std::abs(samples[i]);
    }

    // 归一化到0-1范围
    float avgAmp = sum / (sampleCount * 32768.0f);
    return avgAmp;
}
