"""GMCP and MSDP package support for rich MUD clients."""

from __future__ import annotations

import logging
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from mudlib.player import Player

log = logging.getLogger(__name__)


def send_char_vitals(player: Player) -> None:
    """Send Char.Vitals — pl, max_pl, stamina, max_stamina."""
    if not player.gmcp_enabled:
        return
    player.send_gmcp(
        "Char.Vitals",
        {
            "pl": round(player.pl, 1),
            "max_pl": round(player.max_pl, 1),
            "stamina": round(player.stamina, 1),
            "max_stamina": round(player.max_stamina, 1),
        },
    )


def send_char_status(player: Player) -> None:
    """Send Char.Status — flying, resting, mode, in_combat."""
    if not player.gmcp_enabled:
        return
    player.send_gmcp(
        "Char.Status",
        {
            "flying": player.flying,
            "resting": player.resting,
            "mode": player.mode,
            "in_combat": player.mode == "combat",
        },
    )


def send_room_info(player: Player) -> None:
    """Send Room.Info — zone, coordinates, terrain, exits."""
    if not player.gmcp_enabled:
        return
    from mudlib.zone import Zone

    zone = player.location
    if not isinstance(zone, Zone):
        return

    terrain = zone.get_tile(player.x, player.y)

    # Build exits list from passable adjacent tiles
    exits = []
    directions = [
        ("north", 0, -1),
        ("south", 0, 1),
        ("east", 1, 0),
        ("west", -1, 0),
        ("northeast", 1, -1),
        ("northwest", -1, -1),
        ("southeast", 1, 1),
        ("southwest", -1, 1),
    ]
    for name, dx, dy in directions:
        nx, ny = player.x + dx, player.y + dy
        if zone.is_passable(nx, ny):
            exits.append(name)

    player.send_gmcp(
        "Room.Info",
        {
            "zone": zone.name,
            "x": player.x,
            "y": player.y,
            "terrain": terrain,
            "exits": exits,
        },
    )


def send_map_data(player: Player) -> None:
    """Send Room.Map — terrain viewport around player for client rendering."""
    if not player.gmcp_enabled:
        return
    from mudlib.zone import Zone

    zone = player.location
    if not isinstance(zone, Zone):
        return

    radius = 10
    rows = []
    for dy in range(-radius, radius + 1):
        row = []
        for dx in range(-radius, radius + 1):
            tx = player.x + dx
            ty = player.y + dy
            wx, wy = zone.wrap(tx, ty)
            row.append(zone.terrain[wy][wx])
        rows.append(row)

    player.send_gmcp(
        "Room.Map",
        {
            "x": player.x,
            "y": player.y,
            "radius": radius,
            "terrain": rows,
        },
    )


def send_msdp_vitals(player: Player) -> None:
    """Send MSDP variable updates for real-time gauges.

    Skips sending if values haven't changed since last send.
    """
    if not player.msdp_enabled:
        return
    data = {
        "HEALTH": str(round(player.pl, 1)),
        "HEALTH_MAX": str(round(player.max_pl, 1)),
        "STAMINA": str(round(player.stamina, 1)),
        "STAMINA_MAX": str(round(player.max_stamina, 1)),
    }
    if data == player._last_msdp:
        return
    player._last_msdp = data
    player.send_msdp(data)
