"""Command-line interface for karttapullautin2tiles using cyclopts."""

import json
import sys
from pathlib import Path

import cyclopts
from mercantile import Tile

import karttapullautin2tiles as k2t

app = cyclopts.App()


@app.command
def list_tiles(dir: Path, *, proj: str = "EPSG:25832", pattern="*depr*.pgw", zoom: int = 12):
    """
    List the tiles that are covered by the karttapullautin output directory at the given zoom level.

    The main purpose of this command is to generate a list of tiles that can be passed (possibly in chunks)
    to the `make-tiles` command.

    Parameters
    ----------
    dir
        Input directory (karttapullautin output dir)
    proj
        EPSG string of the projection used
    pattern
        Search pattern for the pgw files
    zoom
        Zoom level to generate tiles for. When running `make-tiles`, all karttapullautin png files for this
        tile need to fit in memory.
    """
    for tile in k2t.list_tiles(dir, proj=proj, pattern=pattern, min_zoom=zoom):
        sys.stdout.write(json.dumps(tile._asdict()) + "\n")


@app.command
def make_tiles(
    in_dir: Path,
    out_dir: Path,
    tile_list: Path | None = None,
    *,
    proj: str = "EPSG:25832",
    pattern="*depr*.pgw",
    max_zoom: int = 17,
    include_viewer: bool = True,
):
    """
    Create a web mercator tiles from karttapullautin output, given a list of tile coordinates.

    The list of tiles is typically generated by the `list-tiles` command. You can split it in chunks
    and pass it to multiple instances of `make-tiles`, e.g. to parallelize (see examples). The format of the tile list
    is one json record per row, of the format `{"x": 2162, "y": 1432, "z": 12}`. The list of tiles defines
    the lowest zoom level for which tiles will be generated. All "child" tiles up to `max_zoom` will also be generated.

    Note that all images required for a tile at min_zoom need to fit in memory. If you have
    memory issues, consider setting a higher zoom level.

    Some Examples:

    * Generate tile list and generate tile output dir with a single process:

    .. code-block:: bash

        k2t list-tiles --zoom 12 karttapullautin/out | k2t make-tiles karttapullautin/out karttapullautin/tiles

    * To run with 6 processes in parallel using GNU parallel:

    .. code-block:: bash

        k2t list-tiles --zoom 12 karttapullautin/out | parallel --pipe -j 6 --block 1 k2t make-tiles karttapullautin/out karttapullautin/tiles

    Parameters
    ----------
    in_dir
        Input directory containing karttapullautin output files
    out_dir
        Output directory for tiles (z/x/y folder structure)
    tile_list
        File with tiles to process. If not provided as file, will be read from stdin.
        This file is typically generated by `k2t list-tiles`.
        The file must contain one json string per row of the format `{"x": 2162, "y": 1432, "z": 12}`
    proj
        EPSG string of the projection used by input images
    pattern
        Search pattern for pgw files in the input directory
    max_zoom
        Maximum zoom level to generate tiles for
    include_viewer
        If enabled, include a HTML file to preview the generated tiles
    """
    if tile_list is None:
        lines = sys.stdin.readlines()
    else:
        with tile_list.open("r") as f:
            lines = f.readlines()

    tiles = [Tile(**json.loads(tile_json)) for tile_json in lines]
    if not len(tiles):
        return

    out_dir.mkdir(parents=True, exist_ok=True)
    k2t.make_tiles(in_dir, out_dir, tiles, proj=proj, pattern=pattern, max_zoom=max_zoom)
    if include_viewer:
        html = k2t.get_html_viewer(
            *k2t._get_tiles_center(tiles), default_zoom=tiles[0].z, min_zoom=tiles[0].z, max_zoom=-max_zoom
        )  # type: ignore
        (out_dir / "viewer.html").write_text(html)


if __name__ == "__main__":
    app()
