class_name CombatMap
extends Node2D

signal tile_hovered(coords: Vector2i)

@export var tile_set: DLTileset
@onready var tile_map: TileMapLayer = %TerrainLayer
@onready var highlight_map: GridOverlay = %OverlayLayer

const TILE_SIZE := 48.0
const SOURCE_ID: int = 0

var _pending_layout: String
var _pending_units: Array[Dictionary] = []


func _ready() -> void:
	if _pending_layout:
		_apply_layout(_pending_layout)
	for entry in _pending_units:
		_apply_deploy(entry.unit, entry.coords)
	_pending_units.clear()


func snap_to_grid(pos: Vector2) -> Vector2:
	return Vector2(floorf(pos.x / TILE_SIZE), floorf(pos.y / TILE_SIZE)) * TILE_SIZE

func world_to_coords(pos: Vector2) -> Vector2i:
	return Vector2i(snap_to_grid(pos) / TILE_SIZE)

func coords_to_world(coords: Vector2i) -> Vector2:
	return Vector2(coords) * TILE_SIZE

func draw_wall(coords: Vector2i) -> void:
	draw_custom(coords, tile_set.wall_tile_coords)

func draw_floor(coords: Vector2i) -> void:
	draw_custom(coords, tile_set.floor_tile_coords)
	
func draw_custom(coords: Vector2i, tile_coords: Vector2i) -> void:
	tile_map.set_cell(coords, SOURCE_ID, tile_coords)

func load_map(layout: String) -> void:
	if is_node_ready():
		_apply_layout(layout)
	else:
		_pending_layout = layout


func deploy_unit(unit: Unit, coords: Vector2i) -> void:
	if is_node_ready():
		_apply_deploy(unit, coords)
	else:
		_pending_units.append({unit = unit, coords = coords})


func _apply_layout(layout: String) -> void:
	var rows := layout.split("\n")
	for y in rows.size():
		for x in rows[y].length():
			var coords := Vector2i(x, y)
			match rows[y][x]:
				"#":
					draw_wall(coords)
				".":
					draw_floor(coords)


func _apply_deploy(unit: Unit, coords: Vector2i) -> void:
	unit.position = coords_to_world(coords)
	add_child(unit)


func is_wall(coords: Vector2i) -> bool:
	return tile_map.get_cell_atlas_coords(coords) == tile_set.wall_tile_coords
	
func remove_unit(unit: Unit) -> void:
	if unit.get_parent() == self:
		remove_child(unit)


func target_tile(coords: Vector2i) -> void:
	highlight_map.target_tile(coords)
	tile_hovered.emit(coords)
