#pragma once
#include <cstddef>
#include <cstdint>

// 80 ms PCM frames: short utterances are complete before playback; longer
// utterances retain 2.56 s at startup and 1.28 s after an underrun.
struct SpeechBufferPolicy {
    static constexpr unsigned prebuffer_frames = 32;
    static constexpr unsigned rebuffer_frames = 16;
    // First progress acknowledgment follows eight played frames; stay inside
    // the Gateway's 64-frame credit window without needing an early ACK.
    static_assert(prebuffer_frames + 8 < 64);
    static constexpr unsigned short_frames = 50;
    bool playing = false;
    bool started = false;
    bool complete = false;
    bool short_utterance = false;
    // Same finite bound while downloading a short sentence or rebuffering.
    // Individual WSS frames can take >3 s on a lossy link.
    static constexpr uint32_t receive_idle_ms = 10000;
    void start(size_t pcm_bytes, size_t frame_bytes) {
        playing = complete = started = false;
        short_utterance = pcm_bytes && pcm_bytes <= frame_bytes * short_frames;
    }
    bool ready(unsigned queued) {
        // An underrun needs a fresh reserve. Resuming on
        // one newly arrived 80 ms frame produces repeated audible gaps.
        if (playing && !complete && queued == 0) playing = false;
        const unsigned reserve = started ? rebuffer_frames : prebuffer_frames;
        if (!playing && (complete || (!short_utterance && queued >= reserve))) {
            playing = true;
            started = true;
        }
        return playing && queued;
    }
    bool stalled(unsigned queued, uint32_t age_ms) const {
        return !complete && age_ms >= receive_idle_ms && (!playing || queued == 0);
    }
};
