"""Abstract WorldInterface — the contract every game-world adapter must fulfil.

Follows a Gymnasium-inspired pattern: observe → act → speak, with each
method returning strongly-typed data structures.

Any future engine (TES3MP, Luanti, Godot, …) plugs in by subclassing
``WorldInterface`` and implementing the three methods.
"""

from __future__ import annotations

from abc import ABC, abstractmethod

from infrastructure.world.types import ActionResult, CommandInput, PerceptionOutput


class WorldInterface(ABC):
    """Engine-agnostic base class for world adapters.

    Subclasses must implement:
        - ``observe()``  — gather structured perception from the world
        - ``act()``      — dispatch a command and return the outcome
        - ``speak()``    — send a message to an NPC / player / broadcast

    Lifecycle hooks ``connect()`` and ``disconnect()`` are optional.
    """

    # -- lifecycle (optional overrides) ------------------------------------

    def connect(self) -> None:  # noqa: B027
        """Establish connection to the game world.

        Default implementation is a no-op.  Override to open sockets,
        authenticate, etc.
        """

    def disconnect(self) -> None:  # noqa: B027
        """Tear down the connection.

        Default implementation is a no-op.
        """

    @property
    def is_connected(self) -> bool:
        """Return ``True`` if the adapter has an active connection.

        Default returns ``True``.  Override for adapters that maintain
        persistent connections.
        """
        return True

    # -- core contract (must implement) ------------------------------------

    @abstractmethod
    def observe(self) -> PerceptionOutput:
        """Return a structured snapshot of the current world state."""

    @abstractmethod
    def act(self, command: CommandInput) -> ActionResult:
        """Execute *command* in the world and return the result."""

    @abstractmethod
    def speak(self, message: str, target: str | None = None) -> None:
        """Send *message* in the world, optionally directed at *target*."""
