/*
    * A2dp.hpp
    * Bluetooth A2DP (Advanced Audio Distribution Profile)
    * AVDTP signaling and SBC audio streaming
    * Copyright (c) 2026 Daniel Hammer
*/

#pragma once
#include <cstdint>

namespace Drivers::USB::Bluetooth::A2dp {

    // =========================================================================
    // A2DP stream states
    // =========================================================================

    enum class State {
        Idle,           // No A2DP connection
        Discovering,    // AVDTP discover in progress
        Configured,     // Stream endpoint configured
        Open,           // Stream open, ready for audio
        Streaming       // Actively streaming audio
    };

    // =========================================================================
    // Public API
    // =========================================================================

    // Drive the A2DP source role after an ACL link is up: open the AVDTP
    // signaling channel, negotiate an SBC stream, and open the media transport
    // channel.  Must be called from process context (it blocks on the AVDTP
    // handshakes), NOT from an event/interrupt path.  Leaves the stream Open.
    bool StartSource(uint32_t timeoutMs = 5000);

    // Called by L2CAP when an AVDTP channel becomes ready
    void OnChannelReady(uint16_t l2capCid);

    // Process an AVDTP signaling packet
    void ProcessAvdtp(const uint8_t* data, uint16_t len);

    // Process an SDP packet (on any SDP L2CAP channel).  Dispatches by PDU:
    // requests (the headset querying OUR services) are answered by the minimal
    // SDP server; responses on our outgoing client channel complete DoSdpQuery.
    void ProcessSdp(uint16_t localCid, const uint8_t* data, uint16_t len);

    // Configure a stream for the given PCM parameters
    bool ConfigureStream(uint32_t sampleRate, uint8_t channels, uint8_t bitsPerSample);

    // Start streaming
    bool StartStream();

    // Stop streaming.  flushQueued drops any PCM still queued in the media
    // ring: pass true when closing the stream (track change / app exit),
    // false for a pause so resume continues gaplessly.
    bool StopStream(bool flushQueued = true);

    // Write PCM audio data to the Bluetooth audio stream.  Copies into the
    // media ring and returns immediately (never blocks); returns the number
    // of bytes accepted (0 = ring full, retry later).
    int WriteAudio(const uint8_t* pcmData, uint32_t pcmLen);

    // Encode + send queued PCM, paced to the audio clock and gated on ACL TX
    // readiness.  Called from the idle-loop event pump and from WriteAudio;
    // self-serializing, cheap no-op when not streaming.
    void PumpMedia();

    // Get current state
    State GetState();

    // Check if currently streaming
    bool IsStreaming();

    // Get volume (0-100)
    int GetVolume();

    // Set volume (0-100)
    void SetVolume(int percent);

}
