from typing import overload

import numpy as np
from numpy.typing import NDArray

from ._typing import ArrayLike, ArrayLikeSeq, OptGeoArrayLike, OptGeoArrayLikeSeq
from .lib import Geometry

__all__ = [
    "area",
    "bounds",
    "distance",
    "frechet_distance",
    "hausdorff_distance",
    "length",
    "minimum_bounding_radius",
    "minimum_clearance",
    "total_bounds",
]

@overload
def area(geometry: Geometry | None, **kwargs) -> np.float64: ...
@overload
def area(geometry: OptGeoArrayLikeSeq, **kwargs) -> NDArray[np.float64]: ...

@overload
def distance(a: Geometry | None, b: Geometry | None, **kwargs) -> np.float64: ...
@overload
def distance(a: OptGeoArrayLikeSeq, b: OptGeoArrayLike, **kwargs) -> NDArray[np.float64]: ...
@overload
def distance(a: OptGeoArrayLike, b: OptGeoArrayLikeSeq, **kwargs) -> NDArray[np.float64]: ...

def bounds(geometry: OptGeoArrayLike, **kwargs) -> NDArray[np.float64]: ...
def total_bounds(geometry: OptGeoArrayLike, **kwargs) -> NDArray[np.float64]: ...

@overload
def length(geometry: Geometry | None, **kwargs) -> np.float64: ...
@overload
def length(geometry: OptGeoArrayLikeSeq, **kwargs) -> NDArray[np.float64]: ...

@overload
def hausdorff_distance(a: Geometry | None, b: Geometry | None, densify: float | None = None, **kwargs) -> np.float64: ...
@overload
def hausdorff_distance(a: OptGeoArrayLike, b: OptGeoArrayLike, densify: ArrayLikeSeq[float], **kwargs) -> NDArray[np.float64]: ...
@overload
def hausdorff_distance(
    a: OptGeoArrayLikeSeq, b: OptGeoArrayLike, densify: ArrayLike[float] | None = None, **kwargs
) -> NDArray[np.float64]: ...
@overload
def hausdorff_distance(
    a: OptGeoArrayLike, b: OptGeoArrayLikeSeq, densify: ArrayLike[float] | None = None, **kwargs
) -> NDArray[np.float64]: ...

@overload
def frechet_distance(a: Geometry | None, b: Geometry | None, densify: float | None = None, **kwargs) -> np.float64: ...
@overload
def frechet_distance(a: OptGeoArrayLike, b: OptGeoArrayLike, densify: ArrayLikeSeq[float], **kwargs) -> NDArray[np.float64]: ...
@overload
def frechet_distance(
    a: OptGeoArrayLikeSeq, b: OptGeoArrayLike, densify: ArrayLike[float] | None = None, **kwargs
) -> NDArray[np.float64]: ...
@overload
def frechet_distance(
    a: OptGeoArrayLike, b: OptGeoArrayLikeSeq, densify: ArrayLike[float] | None = None, **kwargs
) -> NDArray[np.float64]: ...

@overload
def minimum_clearance(geometry: Geometry | None, **kwargs) -> np.float64: ...
@overload
def minimum_clearance(geometry: OptGeoArrayLikeSeq, **kwargs) -> NDArray[np.float64]: ...

@overload
def minimum_bounding_radius(geometry: Geometry | None, **kwargs) -> np.float64: ...
@overload
def minimum_bounding_radius(geometry: OptGeoArrayLikeSeq, **kwargs) -> NDArray[np.float64]: ...
