#pragma once

#include "CwSidetoneSinkBackend.h"

#include <QAudioFormat>
#include <QByteArray>
#include <QObject>
#include <QPointer>

class QAudioSink;
class QIODevice;
class QTimer;

namespace AetherSDR {

// QAudioSink-based sidetone backend.  Push-mode loop: a 2 ms QTimer
// tops up the sink's buffer with samples generated by the
// CwSidetoneGenerator.  Buffer size is 50 ms because <30 ms causes
// Pulse/PipeWire pull-mode Idle/Active flapping and audible chop.
//
// Net perceived latency on Linux PipeWire: ~25 ms (half the buffer).
// Acceptable for slow CW; high-WPM operators want PortAudio backend.
class CwSidetoneQAudioSink : public QObject, public CwSidetoneSinkBackend {
    Q_OBJECT

public:
    explicit CwSidetoneQAudioSink(QObject* parent = nullptr);
    ~CwSidetoneQAudioSink() override;

    bool start(const QAudioDevice& device,
               int desiredRateHz,
               CwSidetoneGenerator* generator) override;
    void stop() override;
    bool isRunning() const override { return m_sink != nullptr; }
    int  actualRateHz() const override { return m_actualRate; }
    const char* name() const override { return "QAudioSink"; }
    QString deviceDescription() const override { return m_deviceDescription; }
    bool fallbackOccurred() const override { return m_fallbackOccurred; }
    QString fallbackReason() const override { return m_fallbackReason; }

private:
    void onTimerTick();

    QAudioSink*          m_sink{nullptr};
    QPointer<QIODevice>  m_device;
    QTimer*              m_timer{nullptr};
    CwSidetoneGenerator* m_generator{nullptr};
    int                  m_actualRate{0};
    QString              m_deviceDescription;
    bool                 m_fallbackOccurred{false};
    QString              m_fallbackReason;
    // VB-Audio Virtual Cable's WASAPI driver only advertises Int16, so the
    // sink probes Float first and falls back to Int16 with a float scratch
    // buffer; the chosen format is stored to keep the pump hot path branchless.
    QAudioFormat::SampleFormat m_sampleFormat{QAudioFormat::Float};
    QByteArray           m_scratch;
};

} // namespace AetherSDR
