/// Audio output trait for the NES APU.
///
/// Implemented by `NativeAudio` (cpal backend)
/// to provide a common interface for audio playback.
#[allow(dead_code)]
pub trait EmulatorAudio {
    /// Send a mono audio sample to the audio output.
    ///
    /// Sends a sample to the audio callback for playback.
    /// If the buffer is full, this will block until the audio callback consumes samples.
    ///
    /// The shared audio pipeline uses **bipolar PCM** in `[-1.0, 1.0]`.
    /// Callers must convert any unsigned/biased source range before calling
    /// this method.  For NES samples (`[0.0, ~1.177]`), use
    /// `normalize_nes_sample()` first.  GB samples are already bipolar after
    /// the APU high-pass filter.
    ///
    /// # Arguments
    /// * `sample` - Bipolar PCM audio sample in the range `-1.0` to `1.0`
    fn queue_sample(&mut self, sample: f32);

    /// Send a stereo `(left, right)` audio sample pair to the audio output.
    ///
    /// Both channels must be bipolar PCM in `[-1.0, 1.0]`.
    /// The default implementation averages left and right and delegates to
    /// [`queue_sample`](Self::queue_sample).  Backends that support true stereo
    /// (e.g. `NativeAudio`) override this.
    fn queue_stereo_sample(&mut self, left: f32, right: f32) {
        self.queue_sample((left + right) / 2.0);
    }

    /// Start audio playback.
    fn resume(&self);

    /// Pause audio playback.
    fn pause(&self);

    /// Set audio volume.
    ///
    /// # Arguments
    /// * `volume` - Volume level from 0.0 (mute) to 1.0 (full volume)
    fn set_volume(&self, volume: f32);

    /// Get current audio volume.
    ///
    /// # Returns
    /// Current volume level from 0.0 to 1.0
    fn get_volume(&self) -> f32;

    /// Pre-fills the audio buffer with silence to avoid startup underruns.
    fn prime_startup(&mut self, samples: usize);

    /// Returns and resets audio stats counters.
    ///
    /// Returns (received_samples, dropped_samples, underrun_samples).
    fn take_and_reset_stats(&self) -> (u64, u64, u64);

    /// Returns the actual sample rate of the opened audio device.
    fn actual_sample_rate(&self) -> i32;

    /// Marks all currently buffered samples as stale so the audio callback
    /// discards them silently before playing new audio.
    ///
    /// Intended to be called after an abrupt state change (e.g. save-state
    /// restore) so pre-change audio does not bleed into post-change playback.
    /// Unlike `pause()`, this does *not* change the paused state.
    fn drain_buffer(&self) {}
}
