"""Text-to-speech via Piper — plays game text aloud in a background thread."""

from __future__ import annotations

import io
import subprocess
import threading
import wave
from pathlib import Path

from piper import PiperVoice


class TTS:
    """Speaks text using Piper TTS and aplay for playback."""

    def __init__(self, model_path: str | Path) -> None:
        self._voice = PiperVoice.load(str(model_path))
        self._thread: threading.Thread | None = None
        self._last_wav: bytes | None = None

    def speak(self, text: str) -> None:
        """Synthesize *text* and play it in a background thread."""
        text = text.strip()
        if not text:
            return

        wav_data = self._synthesize(text)
        self._last_wav = wav_data
        self._play(wav_data)

    def replay(self) -> bool:
        """Replay the last spoken audio. Returns False if nothing to replay."""
        if self._last_wav is None:
            return False
        self._play(self._last_wav)
        return True

    def _synthesize(self, text: str) -> bytes:
        buf = io.BytesIO()
        with wave.open(buf, "wb") as wav_file:
            self._voice.synthesize_wav(text, wav_file)
        return buf.getvalue()

    def _play(self, wav_data: bytes) -> None:
        # Wait for any previous playback to finish
        if self._thread and self._thread.is_alive():
            self._thread.join()
        self._thread = threading.Thread(target=self._play_wav, args=(wav_data,), daemon=True)
        self._thread.start()

    @staticmethod
    def _play_wav(wav_data: bytes) -> None:
        try:
            proc = subprocess.Popen(
                ["aplay", "-q"],
                stdin=subprocess.PIPE,
                stdout=subprocess.DEVNULL,
                stderr=subprocess.DEVNULL,
            )
            proc.communicate(input=wav_data)
        except FileNotFoundError:
            pass  # aplay not available — silently skip
