"""TileMap Domain Tools.

This module provides MCP tools for TileMap and TileMapLayer operations in Godot.
Includes functionality for setting and getting cell data in tilemaps.
"""

import asyncio
from pathlib import Path

from godot_mcp.core import (
    mcp,
    godot_server,
    create_error_response,
    validate_path,
    extract_json_from_output,
)

__all__ = [
    "tilemap_set_cell",
    "tilemap_get_cell",
]


@mcp.tool()
def tilemap_set_cell(
    project_path: str,
    scene_path: str,
    node_path: str,
    x: int,
    y: int,
    source_id: int = 0,
    atlas_x: int = 0,
    atlas_y: int = 0,
    layer: int = 0,
    alternative_tile: int = 0,
) -> str:
    """Set a cell in a TileMap or TileMapLayer node.

    Category: TileMap

    Args:
        project_path: Path to the Godot project directory
        scene_path: Path to the scene file (relative to project)
        node_path: Path to the TileMap or TileMapLayer node (e.g., "root/TileMap")
        x: X coordinate of the cell
        y: Y coordinate of the cell
        source_id: ID of the tile source/tileset (default: 0)
        atlas_x: X coordinate in the tile atlas (default: 0)
        atlas_y: Y coordinate in the tile atlas (default: 0)
        layer: Layer index for TileMap nodes (ignored for TileMapLayer, default: 0)
        alternative_tile: Alternative tile ID (default: 0)
    """
    if not project_path or not scene_path or not node_path:
        return create_error_response("Project path, scene path, and node path are required")

    if not validate_path(project_path) or not validate_path(scene_path):
        return create_error_response("Invalid path")

    try:
        # Check if the project directory exists and contains a project.godot file
        project_file = Path(project_path) / "project.godot"
        if not project_file.exists():
            return create_error_response(
                f"Not a valid Godot project: {project_path}",
                ["Ensure the path points to a directory containing a project.godot file"],
            )

        # Check if the scene file exists
        scene_full_path = Path(project_path) / scene_path
        if not scene_full_path.exists():
            return create_error_response(
                f"Scene file does not exist: {scene_path}",
                [
                    "Ensure the scene path is correct",
                    "Use scene_create to create a new scene first",
                ],
            )

        # Prepare parameters for the operation
        params = {
            "scenePath": scene_path,
            "nodePath": node_path,
            "x": x,
            "y": y,
            "sourceId": source_id,
            "atlasX": atlas_x,
            "atlasY": atlas_y,
            "layer": layer,
            "alternativeTile": alternative_tile,
        }

        # Execute the operation
        stdout, stderr = asyncio.run(
            godot_server.execute_operation("set_tilemap_cell", params, project_path)
        )

        if stderr and "Failed to" in stderr:
            return create_error_response(
                f"Failed to set tilemap cell: {stderr}",
                [
                    "Check if the node path points to a TileMap or TileMapLayer",
                    "Ensure the TileSet is configured with a valid source",
                ],
            )

        return f"TileMap cell set successfully at ({x}, {y})"
    except Exception as error:
        return create_error_response(
            f"Failed to set tilemap cell: {error}",
            [
                "Ensure Godot is installed correctly",
                "Verify the project path is accessible",
            ],
        )


@mcp.tool()
def tilemap_get_cell(
    project_path: str,
    scene_path: str,
    node_path: str,
    x: int,
    y: int,
    layer: int = 0,
) -> str:
    """Get cell data from a TileMap or TileMapLayer node.

    Category: TileMap

    Args:
        project_path: Path to the Godot project directory
        scene_path: Path to the scene file (relative to project)
        node_path: Path to the TileMap or TileMapLayer node (e.g., "root/TileMap")
        x: X coordinate of the cell
        y: Y coordinate of the cell
        layer: Layer index for TileMap nodes (ignored for TileMapLayer, default: 0)

    Returns:
        JSON containing cell data: source_id, atlas_coords, alternative_tile, is_empty
    """
    if not project_path or not scene_path or not node_path:
        return create_error_response("Project path, scene path, and node path are required")

    if not validate_path(project_path) or not validate_path(scene_path):
        return create_error_response("Invalid path")

    try:
        # Check if the project directory exists and contains a project.godot file
        project_file = Path(project_path) / "project.godot"
        if not project_file.exists():
            return create_error_response(
                f"Not a valid Godot project: {project_path}",
                ["Ensure the path points to a directory containing a project.godot file"],
            )

        # Check if the scene file exists
        scene_full_path = Path(project_path) / scene_path
        if not scene_full_path.exists():
            return create_error_response(
                f"Scene file does not exist: {scene_path}",
                [
                    "Ensure the scene path is correct",
                ],
            )

        # Prepare parameters for the operation
        params = {
            "scenePath": scene_path,
            "nodePath": node_path,
            "x": x,
            "y": y,
            "layer": layer,
        }

        # Execute the operation
        stdout, stderr = asyncio.run(
            godot_server.execute_operation("get_tilemap_cell", params, project_path)
        )

        if stderr and "Failed to" in stderr:
            return create_error_response(
                f"Failed to get tilemap cell: {stderr}",
                [
                    "Check if the node path points to a TileMap or TileMapLayer",
                ],
            )

        # Extract and return the JSON output from the GDScript
        return extract_json_from_output(stdout)
    except Exception as error:
        return create_error_response(
            f"Failed to get tilemap cell: {error}",
            [
                "Ensure Godot is installed correctly",
                "Verify the project path is accessible",
            ],
        )
