import typing as t
from collections.abc import Collection, Iterable, Iterator, Sequence

__version__: str
__build_profile__: t.Literal["debug", "release"]
__build_timestamp__: str
__authors__: str
__description__: str
__pkg_name__: str

TILETYPE_GIF: int
TILETYPE_JPG: int
TILETYPE_JSON: int
TILETYPE_PBF: int
TILETYPE_PBFGZ: int
TILETYPE_PNG: int
TILETYPE_UNKNOWN: int
TILETYPE_WEBP: int

class TileDict(t.TypedDict):
    x: int
    y: int
    z: int

_TileEncodingStr: t.TypeAlias = t.Literal[
    "uncompressed",
    "internal",
    "zlib",
    "gzip",
    "brotli",
    "zstd",
]
_TileFormatStr: t.TypeAlias = t.Literal[
    "png",
    "webp",
    "pbf",
    "mvt",
    "gif",
    "jpg",
    "jpeg",
    "json",
    "geojson",
]

class TileType:
    def __init__(self, format: _TileFormatStr, encoding: _TileEncodingStr) -> None: ...
    @property
    def format(self) -> _TileFormatStr: ...
    @property
    def encoding(self) -> _TileEncodingStr: ...
    @classmethod
    def from_bytes(cls, buf: bytes) -> TileType: ...
    def __eq__(self, other: object) -> bool: ...

class LngLat:
    lat: float
    lng: float

    @classmethod
    def __init__(cls, lng: float, lat: float) -> None: ...
    @classmethod
    def from_tile(cls, tile: Tile) -> t.Any: ...
    def members(self) -> tuple[float, float]: ...
    def __eq__(self, other: object) -> bool: ...
    def __ge__(self, other: t.Any) -> bool: ...
    def __getitem__(self, index: int) -> float: ...
    def __gt__(self, other: t.Any) -> bool: ...
    def __le__(self, other: t.Any) -> bool: ...
    def __len__(self) -> int: ...
    def __lt__(self, other: t.Any) -> bool: ...
    def __ne__(self, other: object) -> bool: ...
    def __hash__(self) -> int: ...
    def __iter__(self) -> Iterator[float]: ...

class Bbox:
    right: float
    top: float
    bottom: float
    left: float

    def __init__(
        self, right: float, top: float, left: float, bottom: float
    ) -> None: ...
    @classmethod
    def from_tile(cls, tile: Tile) -> Bbox: ...
    def members(self) -> tuple[float, float, float, float]: ...
    @t.overload
    def __getitem__(self, index: int) -> float: ...
    @t.overload
    def __getitem__(self, index: slice) -> tuple[float, ...]: ...
    def __len__(self) -> int: ...
    def __hash__(self) -> int: ...
    def __iter__(self) -> Iterator[float]: ...
    def tuple(self) -> tuple[float, float, float, float]: ...
    def __eq__(self, other: object) -> bool: ...
    def __ge__(self, other: t.Any) -> bool: ...

class LngLatBbox:
    east: float
    north: float
    south: float
    west: float

    def __init__(
        self, east: float, north: float, west: float, south: float
    ) -> None: ...
    @classmethod
    def from_tile(cls, tile: Tile) -> LngLatBbox: ...
    def members(self) -> tuple[float, float, float, float]: ...
    @t.overload
    def __getitem__(self, index: int) -> float: ...
    @t.overload
    def __getitem__(self, index: slice) -> tuple[float, ...]: ...
    def __len__(self) -> int: ...
    def __hash__(self) -> int: ...
    def __iter__(self) -> Iterator[float]: ...
    def tuple(self) -> tuple[float, float, float, float]: ...
    def __eq__(self, other: object) -> bool: ...
    def __ge__(self, other: t.Any) -> bool: ...

class Tile:
    def __init__(self, x: int, y: int, z: int) -> None: ...
    def bounds(self) -> LngLatBbox: ...
    def children(self, zoom: int = 1, zorder: bool = False) -> list[Tile]: ...
    def children1(self, zorder: bool = False) -> tuple[Tile, Tile, Tile, Tile]:
        """return direct children of the tile"""

    def flipy(self) -> Tile: ...
    @property
    def x(self) -> int: ...
    @property
    def y(self) -> int: ...
    @property
    def z(self) -> int: ...
    @classmethod
    def from_lnglat_zoom(cls, lng: float, lat: float, zoom: int) -> Tile: ...
    @classmethod
    def from_quadkey(cls, quadkey: str) -> Tile: ...
    @classmethod
    def from_qk(cls, qk: str) -> Tile: ...
    @classmethod
    def from_pmtileid(cls, pmtileid: int) -> Tile: ...
    @classmethod
    def from_row_major_id(cls, rmid: int) -> Tile: ...
    @classmethod
    def from_rmid(cls, rmid: int) -> Tile: ...
    def pmtileid(self) -> int: ...
    def parent_pmtileid(self) -> int: ...
    def row_major_id(self) -> tuple[int, int, int]: ...
    def rmid(self) -> tuple[int, int, int]: ...
    def json(self, obj: bool) -> str: ...
    def json_arr(self) -> str: ...
    def json_obj(self) -> str: ...
    def ll(self) -> LngLat: ...
    def lr(self) -> LngLat: ...
    def members(self) -> tuple[int, int, int]: ...
    def neighbors(self) -> list[Tile]: ...
    def parent(self) -> Tile: ...
    def siblings(self) -> list[Tile]: ...
    def ul(self) -> LngLat: ...
    def ur(self) -> LngLat: ...
    def __eq__(self, other: object) -> bool: ...
    def __ge__(self, other: Tile | tuple[int, int, int]) -> bool: ...
    def qk(self) -> str: ...
    def quadkey(self) -> str: ...
    def fmt_zxy(self, sep: str | None) -> str: ...
    def fmt_zxy_ext(self, ext: str, sep: str | None) -> str: ...
    @t.overload
    def __getitem__(self, index: int) -> int: ...
    @t.overload
    def __getitem__(self, index: slice) -> tuple[int, ...]: ...
    def __gt__(self, other: t.Any) -> bool: ...
    def __invert__(self) -> Tile: ...
    def __le__(self, other: Tile) -> bool: ...
    def __len__(self) -> int: ...
    def __lt__(self, other: Tile) -> bool: ...
    def __ne__(self, other: object) -> bool: ...
    def __hash__(self) -> int: ...
    def tuple(self) -> tuple[int, int, int]: ...
    def __iter__(self) -> Iterator[int]: ...
    def valid(self) -> bool: ...
    def asdict(self) -> TileDict: ...
    def feature(
        self,
        fid: str | None = ...,
        props: dict[t.Any, t.Any] | None = ...,
        projected: str | None = ...,
        buffer: float | None = ...,
        precision: int | None = ...,
    ) -> t.Any: ...
    def center(self) -> LngLat: ...

class TileFmts:
    def __init__(self, fmt: str) -> None: ...
    def fmt(self, *args: TileLike) -> str: ...
    def format(self, *args: TileLike) -> str: ...
    def __str__(self) -> str: ...
    def __eq__(self, other: object) -> bool: ...
    @property
    def fmtstr(self) -> str:
        """Return format-template string"""

TileLike: t.TypeAlias = Tile | tuple[int, int, int] | list[int] | int

def _parse_tile_arg(*args: TileLike) -> Tile: ...
def _xy(
    lng: float, lat: float, truncate: bool | None = None
) -> tuple[float, float]: ...
def bounding_tile(
    *bbox: Bbox | tuple[float, float] | float, truncate: bool = ...
) -> Tile: ...
def bounds(tile: TileLike) -> LngLatBbox: ...
def children(*tile: TileLike, zoom: int | None = ...) -> list[Tile]: ...
def feature(
    tile: TileLike,
    fid: str | None = ...,
    props: dict[t.Any, t.Any] | None = ...,
    projected: str | None = ...,
    buffer: float | None = ...,
    precision: int | None = ...,
) -> t.Any: ...
def from_tuple(tile: tuple[int, int, int]) -> Tile: ...
def lnglat(lng: float, lat: float, truncate: bool | None = None) -> LngLat: ...
def minmax(zoom: int) -> tuple[int, int]: ...
def neighbors(*tile: TileLike) -> list[Tile]: ...
def parent(*tile: TileLike, zoom: int | None = ...) -> Tile | None: ...
def parse_tile_arg(*args: TileLike) -> Tile: ...
def quadkey(*tile: TileLike) -> str: ...
def quadkey2xyz(qk: str) -> Tile: ...
def quadkey_to_tile(qk: str) -> Tile: ...
def tile(lng: float, lat: float, zoom: int, truncate: bool | None = None) -> Tile: ...
def tiles(
    west: float,
    south: float,
    east: float,
    north: float,
    zooms: list[int] | tuple[int, ...] | int,
    truncate: bool = ...,
) -> Collection[Tile]: ...
def tiles_list(
    west: float,
    south: float,
    east: float,
    north: float,
    zooms: list[int] | tuple[int, ...] | int,
    truncate: bool = ...,
) -> list[Tile]: ...
def tiles_count(
    west: float,
    south: float,
    east: float,
    north: float,
    zooms: list[int] | tuple[int, ...] | int,
    truncate: bool = ...,
) -> int: ...
def pmtileid2xyz(pmtileid: int) -> Tile: ...
def qk2xyz(qk: str) -> Tile: ...
def tiletype(buf: bytes) -> int: ...
def tiletype2headers(tiletype_int: int) -> list[tuple[str, str]]: ...
def tiletype_str(buf: bytes) -> str: ...
def ul(*tile: TileLike) -> LngLat: ...
def xy(lng: float, lat: float, truncate: bool | None = None) -> tuple[float, float]: ...
def xy_bounds(*tile: TileLike) -> Bbox: ...
def xyz2quadkey(x: int, y: int, z: int) -> str: ...
def xyz(x: int, y: int, z: int) -> Tile: ...
def parse_tiles(tilesish: Sequence[TileLike]) -> list[Tile]: ...
def truncate_lnglat(lng: float, lat: float) -> tuple[float, float]: ...
def simplify(tiles: Sequence[TileLike]) -> set[Tile]: ...
def coords(obj: t.Any) -> Iterable[tuple[float, float]]: ...
def _coords(obj: t.Any) -> Iterable[tuple[float, float]]: ...
def geojson_bounds(obj: t.Any) -> LngLatBbox: ...
def pmtileid(*tile: TileLike) -> int: ...
def from_pmtileid(pmtileid: int) -> Tile: ...
def geotransform2optzoom(
    geotransform: tuple[float, float, float, float, float, float],
) -> int: ...
def geojson2tiles(
    geojson_str: str, maxzoom: int, minzoom: int | None = None
) -> list[Tile]: ...
def parse_textiles(string: str) -> list[Tile]: ...

# CLI
def ut_cli(args: list[str]) -> int: ...
def fmt_nbytes(nbytes: int) -> str: ...

# Lager
_LagerLevel: t.TypeAlias = t.Literal["trace", "debug", "info", "warn", "error"]

def set_lager_level(level: _LagerLevel) -> None:
    """set utiles lager level"""

def set_lager_format(json: bool) -> None:
    """set utiles lager format (json true/false)"""

class Lager:
    level: _LagerLevel
    format: t.Literal["full", "json"]

    def __init__(self) -> None: ...
    def trace(self, msg: str) -> None: ...
    def debug(self, msg: str) -> None: ...
    def info(self, msg: str) -> None: ...
    def warn(self, msg: str) -> None: ...
    def error(self, msg: str) -> None: ...
