"""Geographic DTOs shared by every component that crosses the WGS / ENU / tile-pixel
boundary.

Consumed by `helpers.wgs_converter` (AZ-279), C4 / C5 / C6 / C8 / C10 / C11 / C12.
"""

from __future__ import annotations

from dataclasses import dataclass


@dataclass(frozen=True, slots=True)
class LatLonAlt:
    """A WGS84 geographic position. ``alt_m`` is height above the WGS84 ellipsoid.

    ``slots=True`` per AZ-355 AC-2 — DTOs cross component boundaries
    and mutation-through-aliasing has bitten this codebase before
    (R05 in the C5 risk register, R10 in the C4 risk register).
    """

    lat_deg: float
    lon_deg: float
    alt_m: float


@dataclass(frozen=True)
class BoundingBox:
    """An axis-aligned lat/lon bounding box.

    The slippy-map tile bounds returned by ``WgsConverter.tile_xy_to_latlon_bounds``
    use this shape. Latitude axis grows northward; longitude axis grows eastward.
    """

    min_lat_deg: float
    min_lon_deg: float
    max_lat_deg: float
    max_lon_deg: float

    def contains(self, lat_deg: float, lon_deg: float) -> bool:
        return (
            self.min_lat_deg <= lat_deg <= self.max_lat_deg
            and self.min_lon_deg <= lon_deg <= self.max_lon_deg
        )
