# -*- coding: utf-8 -*-
"""Adapter layer over `discord-ext-voice-recv` (vendored at vendor/).

If discord-ext-voice-recv breaks, swap to py-cord by rewriting only this file.
Contract test in tests/test_voice_adapter_contract.py guards drift.

Downstream consumers (`src/voice/*`, `src/adapters/discord_voice.py`) MUST
import from this file — never from `discord.ext.voice_recv` directly.

## Public API surface (stable across upstream changes)

- ``VoiceReceiveClient`` — alias for ``voice_recv.VoiceRecvClient``. Subclass
  of ``discord.VoiceClient`` with extra audio-receive plumbing.
  Key methods used by the pipeline:
    * ``await client.disconnect(force: bool = False)`` (from discord.VoiceClient)
    * ``client.listen(sink, *, after=None)`` — attach an ``AudioSink``;
      raises ``discord.ClientException`` if not connected or already listening
    * ``client.stop_listening()`` — detach the current sink
    * ``client.is_listening() -> bool``
    * ``client.stop()`` — stop both playing and listening
    * ``client.sink`` (property, getter+setter) — swap the active sink in place

- ``AudioSink`` — abstract base. Subclasses MUST implement:
    * ``write(user: Optional[discord.User|Member], data: VoiceData) -> None``
    * ``wants_opus() -> bool`` (True → receive opus bytes; False → receive PCM)
    * ``cleanup() -> None``

- ``VoiceData`` — per-packet container. Slots: ``packet``, ``source``, ``pcm``.
  ``.pcm`` is decoded 48kHz s16le stereo bytes when ``wants_opus()`` is False.
  ``.opus`` property returns the raw opus bytes from the underlying RTP packet.

- ``connect_voice(channel) -> VoiceReceiveClient`` — async helper, returns a
  connected receive-capable voice client.
"""

from __future__ import annotations

from typing import TYPE_CHECKING

from discord.ext import voice_recv

if TYPE_CHECKING:
    import discord


# --- Stable re-exports -------------------------------------------------------

VoiceReceiveClient = voice_recv.VoiceRecvClient
AudioSink = voice_recv.AudioSink
VoiceData = voice_recv.VoiceData


__all__ = [
    "VoiceReceiveClient",
    "AudioSink",
    "VoiceData",
    "connect_voice",
]


async def connect_voice(channel: "discord.VoiceChannel") -> VoiceReceiveClient:
    """Connect to a Discord voice channel with the receive-capable client.

    Thin wrapper around ``channel.connect(cls=VoiceRecvClient)`` so callers
    don't have to import the vendored class directly.
    """
    return await channel.connect(cls=VoiceReceiveClient)
