"""Resolve the orthogonal Visual × Audio controls into render outputs (audio spec
§4/§6). The single source of truth for: whether the projector shows video, and
which audio url plays for a given (audio source, current altitude).

Replaces player/content.py's 7-way bundled table. Soundtrack follows the single
Altitude dial; off is silence. `white_noise` and `music` are deferred sources —
not in v1 (the live control is a simple Audio on/off toggle where on=soundtrack)."""

from __future__ import annotations

from dataclasses import dataclass

VISUAL_POSITIONS = frozenset({"on", "off"})
# v1 audio sources. The live UI is an Audio on/off toggle (on=soundtrack).
# "white_noise" and "music" are deferred (no live control) and intentionally absent.
AUDIO_SOURCES = frozenset({"off", "soundtrack"})


@dataclass(frozen=True)
class AudioResolution:
    source: str
    url: str | None
    altitude_coupled: bool


def resolve_visual(position: str) -> bool:
    """Visual on/off → whether the renderer shows video (vs fade-to-black)."""
    if position not in VISUAL_POSITIONS:
        raise ValueError(
            f"unknown visual position {position!r}; expected one of {sorted(VISUAL_POSITIONS)}"
        )
    return position == "on"


def resolve_audio_url(source: str, *, scale_audio: str) -> str | None:
    """The audio url for (source, current altitude): soundtrack → the current
    scale's asset (or None if none authored); off → None. `scale_audio` is the ring
    scale's `audio` path (relative to /media/audio/)."""
    if source not in AUDIO_SOURCES:
        raise ValueError(
            f"unknown audio source {source!r}; expected one of {sorted(AUDIO_SOURCES)}"
        )
    if source == "off":
        return None
    # soundtrack — couple to the current altitude's asset
    return f"/media/audio/{scale_audio}" if scale_audio else None


def resolve_audio(source: str, *, scale_audio: str) -> AudioResolution:
    """The full render.audio view: source, resolved url, and whether it follows the
    Altitude dial (true only for soundtrack)."""
    url = resolve_audio_url(source, scale_audio=scale_audio)
    return AudioResolution(source=source, url=url, altitude_coupled=(source == "soundtrack"))
