from typing import overload
from typing_extensions import Unpack, deprecated

from ._typing import GeoArray, OptGeoArrayLike, OptGeoArrayLikeSeq, UFuncKwargs
from .geometry.base import BaseGeometry
from .lib import Geometry

__all__ = [
    "coverage_union",
    "coverage_union_all",
    "difference",
    "disjoint_subset_union",
    "disjoint_subset_union_all",
    "intersection",
    "intersection_all",
    "symmetric_difference",
    "symmetric_difference_all",
    "unary_union",
    "union",
    "union_all",
]

@overload
def difference(a: Geometry, b: Geometry, grid_size: float | None = None, **kwargs: Unpack[UFuncKwargs]) -> BaseGeometry: ...
@overload
def difference(a: None, b: Geometry | None, grid_size: float | None = None, **kwargs: Unpack[UFuncKwargs]) -> None: ...
@overload
def difference(a: Geometry | None, b: None, grid_size: float | None = None, **kwargs: Unpack[UFuncKwargs]) -> None: ...
@overload
def difference(
    a: OptGeoArrayLikeSeq, b: OptGeoArrayLike, grid_size: float | None = None, **kwargs: Unpack[UFuncKwargs]
) -> GeoArray: ...
@overload
def difference(
    a: OptGeoArrayLike, b: OptGeoArrayLikeSeq, grid_size: float | None = None, **kwargs: Unpack[UFuncKwargs]
) -> GeoArray: ...

@overload
def intersection(a: Geometry, b: Geometry, grid_size: float | None = None, **kwargs: Unpack[UFuncKwargs]) -> BaseGeometry: ...
@overload
def intersection(a: None, b: Geometry | None, grid_size: float | None = None, **kwargs: Unpack[UFuncKwargs]) -> None: ...
@overload
def intersection(a: Geometry | None, b: None, grid_size: float | None = None, **kwargs: Unpack[UFuncKwargs]) -> None: ...
@overload
def intersection(
    a: OptGeoArrayLikeSeq, b: OptGeoArrayLike, grid_size: float | None = None, **kwargs: Unpack[UFuncKwargs]
) -> GeoArray: ...
@overload
def intersection(
    a: OptGeoArrayLike, b: OptGeoArrayLikeSeq, grid_size: float | None = None, **kwargs: Unpack[UFuncKwargs]
) -> GeoArray: ...

@overload
def intersection_all(geometries: OptGeoArrayLike, axis: None = None, **kwargs: Unpack[UFuncKwargs]) -> BaseGeometry: ...
@overload
def intersection_all(geometries: OptGeoArrayLikeSeq, axis: int, **kwargs: Unpack[UFuncKwargs]) -> BaseGeometry | GeoArray: ...

@overload
def symmetric_difference(
    a: Geometry, b: Geometry, grid_size: float | None = None, **kwargs: Unpack[UFuncKwargs]
) -> BaseGeometry: ...
@overload
def symmetric_difference(a: None, b: Geometry | None, grid_size: float | None = None, **kwargs: Unpack[UFuncKwargs]) -> None: ...
@overload
def symmetric_difference(a: Geometry | None, b: None, grid_size: float | None = None, **kwargs: Unpack[UFuncKwargs]) -> None: ...
@overload
def symmetric_difference(
    a: OptGeoArrayLikeSeq, b: OptGeoArrayLike, grid_size: float | None = None, **kwargs: Unpack[UFuncKwargs]
) -> GeoArray: ...
@overload
def symmetric_difference(
    a: OptGeoArrayLike, b: OptGeoArrayLikeSeq, grid_size: float | None = None, **kwargs: Unpack[UFuncKwargs]
) -> GeoArray: ...

@overload
@deprecated("symmetric_difference_all behaves incorrectly and will be removed in a future version.")
def symmetric_difference_all(geometries: OptGeoArrayLike, axis: None = None, **kwargs: Unpack[UFuncKwargs]) -> BaseGeometry: ...
@overload
@deprecated("symmetric_difference_all behaves incorrectly and will be removed in a future version.")
def symmetric_difference_all(
    geometries: OptGeoArrayLikeSeq, axis: int, **kwargs: Unpack[UFuncKwargs]
) -> BaseGeometry | GeoArray: ...

@overload
def union(a: Geometry, b: Geometry, grid_size: float | None = None, **kwargs: Unpack[UFuncKwargs]) -> BaseGeometry: ...
@overload
def union(a: None, b: Geometry | None, grid_size: float | None = None, **kwargs: Unpack[UFuncKwargs]) -> None: ...
@overload
def union(a: Geometry | None, b: None, grid_size: float | None = None, **kwargs: Unpack[UFuncKwargs]) -> None: ...
@overload
def union(
    a: OptGeoArrayLikeSeq, b: OptGeoArrayLike, grid_size: float | None = None, **kwargs: Unpack[UFuncKwargs]
) -> GeoArray: ...
@overload
def union(
    a: OptGeoArrayLike, b: OptGeoArrayLikeSeq, grid_size: float | None = None, **kwargs: Unpack[UFuncKwargs]
) -> GeoArray: ...

@overload
def union_all(
    geometries: OptGeoArrayLike, grid_size: float | None = None, axis: None = None, **kwargs: Unpack[UFuncKwargs]
) -> BaseGeometry: ...
@overload
def union_all(
    geometries: OptGeoArrayLikeSeq, grid_size: float | None = None, *, axis: int, **kwargs: Unpack[UFuncKwargs]
) -> BaseGeometry | GeoArray: ...
@overload
def union_all(
    geometries: OptGeoArrayLikeSeq, grid_size: float | None, axis: int, **kwargs: Unpack[UFuncKwargs]
) -> BaseGeometry | GeoArray: ...

unary_union = union_all

@overload
def coverage_union(
    a: OptGeoArrayLike, b: OptGeoArrayLike, *, axis: None = None, **kwargs: Unpack[UFuncKwargs]
) -> BaseGeometry: ...
@overload
def coverage_union(
    a: OptGeoArrayLike, b: OptGeoArrayLike, *, axis: int, **kwargs: Unpack[UFuncKwargs]
) -> BaseGeometry | GeoArray: ...

@overload
def coverage_union_all(geometries: OptGeoArrayLike, axis: None = None, **kwargs: Unpack[UFuncKwargs]) -> BaseGeometry: ...
@overload
def coverage_union_all(geometries: OptGeoArrayLikeSeq, axis: int, **kwargs: Unpack[UFuncKwargs]) -> BaseGeometry | GeoArray: ...

def disjoint_subset_union(a: OptGeoArrayLike, b: OptGeoArrayLike, **kwargs: Unpack[UFuncKwargs]) -> BaseGeometry | GeoArray: ...

@overload
def disjoint_subset_union_all(
    geometries: OptGeoArrayLike, *, axis: None = None, **kwargs: Unpack[UFuncKwargs]
) -> BaseGeometry: ...
@overload
def disjoint_subset_union_all(
    geometries: OptGeoArrayLikeSeq, *, axis: int, **kwargs: Unpack[UFuncKwargs]
) -> BaseGeometry | GeoArray: ...
