"""Visibility mask computation for terrain sheets.

Compute which terrain points are visible from an observer position.
A point is visible if the line of sight from observer to that point
doesn't intersect higher terrain along the way.

This is a thin wrapper around get_shadow_depth -- visibility is simply
the sign of the shadow depth field.

Example::

    from gri_utils import terrain
    import numpy as np

    # Create terrain sheet
    sheet = terrain.lla_to_xyz_sheet(lats, lons, alts)

    # Observer on a hilltop
    observer = terrain.lla_to_xyz_sheet(
        np.array([39.05]), np.array([-105.0]), np.array([[2500]])
    )[0, 0]

    # Get visibility mask (True = visible from observer)
    mask = terrain.get_visibility_mask(sheet, observer)
"""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from collections.abc import Sequence

    import numpy as np
    from numpy.typing import NDArray


def get_visibility_mask(
    sheet_xyz: NDArray[np.floating] | Sequence,
    observer_xyz: NDArray[np.floating] | Sequence,
) -> NDArray[np.bool_]:
    """Compute visibility mask from observer to each terrain point.

    A point is visible if the line of sight from observer to that point
    doesn't intersect higher terrain along the way.

    Args:
        sheet_xyz: Terrain sheet in ECEF meters. Shape (M, N, 3).
        observer_xyz: Observer position in ECEF meters. Shape (3,).

    Returns:
        Boolean mask of shape (M, N). True means point is visible from observer.
    """
    from .shadow_depth import get_shadow_depth  # noqa: PLC0415

    depth = get_shadow_depth(sheet_xyz, observer_xyz)
    return depth > 0
