"""Autopilot operating modes.

The brief (section 3) defines five Phase 1 modes plus three Phase 2 sail
modes that appear greyed-out in the UI but are reserved here for forward
compatibility.
"""

from __future__ import annotations

from enum import StrEnum


class AutopilotMode(StrEnum):
    """The complete set of autopilot operating modes, across both phases.

    Use :func:`is_available_in_phase` to query phase gating instead of
    hard-coding lists in the UI.
    """

    # --- Phase 1 (Sprint 1+) ---
    STANDBY = "standby"
    """Pilot disengaged, helm is manual."""

    HEADING_HOLD = "heading_hold"
    """Holds a fixed magnetic/true compass heading."""

    TRUE_COURSE = "true_course"
    """Holds COG, compensating drift due to current and wind."""

    TRACK_KEEPING = "track_keeping"
    """Follows an ECDIS waypoint route with smooth XTE correction."""

    DODGE = "dodge"
    """Temporary deviation without losing the route; auto-returns when released."""

    # --- Phase 2 (Sprint 10+, greyed in Phase 1 UI) ---
    APPARENT_WIND = "apparent_wind"
    """Holds constant apparent wind angle (vane mode). Sailboats only."""

    TRUE_WIND = "true_wind"
    """Holds constant true wind angle. Sailboats only."""

    AUTO_TACK = "auto_tack"
    """Automatically tacks at a target relative wind angle. Sailboats only."""


_PHASE_1: frozenset[AutopilotMode] = frozenset(
    {
        AutopilotMode.STANDBY,
        AutopilotMode.HEADING_HOLD,
        AutopilotMode.TRUE_COURSE,
        AutopilotMode.TRACK_KEEPING,
        AutopilotMode.DODGE,
    }
)

_PHASE_2: frozenset[AutopilotMode] = frozenset(
    {
        AutopilotMode.APPARENT_WIND,
        AutopilotMode.TRUE_WIND,
        AutopilotMode.AUTO_TACK,
    }
)


def is_available_in_phase(mode: AutopilotMode, phase: int) -> bool:
    """Return ``True`` if ``mode`` is available in the given product phase.

    Phase 1 is the launch product. Phase 2 adds the sailboat wind modes.
    Asking for any other phase number returns ``False``.
    """
    if phase == 1:
        return mode in _PHASE_1
    if phase == 2:
        return mode in _PHASE_1 or mode in _PHASE_2
    return False
