class_name MapLayout extends Resource

@export var size: Vector2i = Vector2i.ZERO
@export var rooms: Array[Room]
## Openings are stored as a flat array of pairs: [from1, to1, from2, to2, ...].
## Each consecutive pair of Vector2i values represents a bidirectional doorway
## between two adjacent tiles in different rooms.
@export var openings: Array[Vector2i]

var _tile_room_map: Dictionary = {}
var _opening_set: Dictionary = {}


func initialize() -> void:
	assert(openings.size() % 2 == 0, "Openings must be provided as pairs of Vector2i")
	_tile_room_map.clear()
	_opening_set.clear()
	for room in rooms:
		for tile in room.tiles:
			_tile_room_map[tile] = room
	for i in range(0, openings.size(), 2):
		var a := openings[i]
		var b := openings[i + 1]
		_opening_set[_edge_key(a, b)] = true


static func _edge_key(a: Vector2i, b: Vector2i) -> String:
	if a < b:
		return "%d,%d-%d,%d" % [a.x, a.y, b.x, b.y]
	return "%d,%d-%d,%d" % [b.x, b.y, a.x, a.y]


func is_tile_valid(tile: Vector2i) -> bool:
	return _tile_room_map.has(tile)


func get_room_at(tile: Vector2i) -> Room:
	return _tile_room_map.get(tile, null)


func is_passable(from: Vector2i, to: Vector2i) -> bool:
	if not is_tile_valid(from) or not is_tile_valid(to):
		return false
	var room_from: Room = _tile_room_map[from]
	var room_to: Room = _tile_room_map[to]
	if room_from == room_to:
		return true
	return _opening_set.has(_edge_key(from, to))


func get_openings() -> Array:
	## Returns an array of [Vector2i, Vector2i] pairs representing opening edges.
	var result: Array = []
	for i in range(0, openings.size(), 2):
		result.append([openings[i], openings[i + 1]])
	return result


func get_walls() -> Array:
	## Returns an array of [Vector2i, Vector2i] pairs representing wall edges.
	## A wall exists where a room tile borders void or a different room (without an opening).
	var walls: Array = []
	var directions := [Vector2i.RIGHT, Vector2i.DOWN, Vector2i.LEFT, Vector2i.UP]
	var visited_edges: Dictionary = {}

	for room in rooms:
		for tile in room.tiles:
			for dir in directions:
				var neighbor: Vector2i = tile + dir
				var key := _edge_key(tile, neighbor)
				if visited_edges.has(key):
					continue
				visited_edges[key] = true

				var neighbor_room: Room = _tile_room_map.get(neighbor, null)
				if neighbor_room == room:
					continue
				# Neighbor is void or different room — wall unless opening
				if not _opening_set.has(key):
					walls.append([tile, neighbor])
	return walls
