import logging
import os
import sys
from pathlib import Path

import typer
from rich.console import Console
from rich.logging import RichHandler

from tilemapper import battlemap
from tilemapper import tileset as _tileset

app = typer.Typer()
app_state = {}


@app.callback(invoke_without_command=True)
def main(
    ctx: typer.Context,
    config_dir: Path = typer.Option(
        default=Path(__file__).parent.parent / "tilesets", help="The path containing tile sets to load."
    ),
    verbose: bool = typer.Option(default=False, help="If True, increase verbosity of status messages."),
):
    app_state["tileset_manager"] = _tileset.TileSetManager(config_dir)
    app_state["config_dir"] = config_dir
    app_state["verbose"] = verbose
    debug = os.getenv("DEBUG", None)
    logging.basicConfig(
        format="%(name)s %(message)s",
        level=logging.DEBUG if debug else logging.INFO,
        handlers=[RichHandler(rich_tracebacks=True, tracebacks_suppress=[typer])],
    )


@app.command()
def list():
    """
    List available tile sets.
    """
    manager = app_state["tileset_manager"]
    print("\n".join(manager.available))


@app.command()
def render(
    source: Path = typer.Argument(help="The battle map text file to load."),
    outfile: Path = typer.Option(help="The file to create. If not specified, print to STDOUT", default=None),
    tileset: str = typer.Option(
        help="The name of the tile set to use (run mapper list to see what's available).", default="colorized"
    ),
):
    """
    Create a rendered battle map using a tile set. Will generate a PNG file if the tile set supports it,
    otherwise text output.
    """
    manager = app_state["tileset_manager"]
    if tileset not in manager.available:
        raise RuntimeError(f"Could not locate the tile set {tileset} in {manager.config_dir}.")

    try:
        bmap = battlemap.BattleMap(name=source.name, source=source, tileset=manager.load(tileset))
        bmap.load()
    except battlemap.UnsupportedTileException as e:
        logging.error(e)
        sys.exit(1)

    try:
        image = bmap.as_image()
        if outfile:
            image.save(outfile)
            outfile.write_text(bmap.render())
            print(f"Wrote {outfile.stat().st_size} bytes to {outfile}")
        else:
            image.save(sys.stdout, "png")
        return
    except NotImplementedError:
        pass
    console = Console()
    console.print(repr(bmap), highlight=False)


if __name__ == "__main__":
    app()
