class_name StandardRoom
extends TileMap

const TILEMAP_LAYER = 0

@export_category("Room Openings")
@export var left: bool = false
@export var right: bool = false
@export var top: bool = false
@export var bottom: bool = false

var room_size: Vector2i 
var cell_size: Vector2i 

func _init() -> void:
	self.room_size = self.get_used_rect().size
	self.cell_size = self.tile_set.tile_size

func is_block() -> bool:
	if self.left or self.right or self.top or self.bottom:
		return false
	return true

func get_exits() -> Array[Vector2i]:
	var exits: Array[Vector2i] = []
	if self.left:
		exits.append(Vector2i.LEFT)
	if self.right:
		exits.append(Vector2i.RIGHT)
	if self.top:
		exits.append(Vector2i.UP)
	if self.bottom:
		exits.append(Vector2i.DOWN)
	return exits

func get_exit_pos(exit: Vector2i) -> Vector2i:
	var pos: Vector2i = Vector2i.ZERO
	if exit == Vector2i.LEFT:
		pos = Vector2i(0, self.room_size.y / 2)
	elif exit == Vector2i.RIGHT:
		pos = Vector2i(self.room_size.x - 1, self.room_size.y / 2)
	elif exit == Vector2i.UP:
		pos = Vector2i(self.room_size.x / 2, 0)
	elif exit == Vector2i.DOWN:
		pos = Vector2i(self.room_size.x / 2, self.room_size.y - 1)
	return pos

func get_exit_pos_offset(edge_pos: Vector2i, exit: Vector2i) -> Vector2i:
	match exit:
		Vector2i.UP:
			return edge_pos + Vector2i(self.room_size.x/-2, self.room_size.y * -1)
		Vector2i.DOWN:
			return edge_pos + Vector2i(self.room_size.x/-2, 1)
		Vector2i.LEFT:
			return edge_pos + Vector2i(-self.room_size.x, -self.room_size.y/2)
		Vector2i.RIGHT:
			return edge_pos + Vector2i(1, -self.room_size.y/2)
		_:
			return Vector2i.ZERO

func copy_to_map(map: TileMap) -> void:
	for x in range(0, self.room_size.x):
		for y in range(0, self.room_size.y):
			var tile = self.get_cell_source_id(TILEMAP_LAYER, Vector2i(x, y))
			var alt = self.get_cell_alternative_tile(TILEMAP_LAYER, Vector2i(x, y))
			
			if tile != -1:
				map.set_cell(TILEMAP_LAYER, Vector2i(position.x + x, position.y + y), tile, Vector2i(0, 0), alt)
			else:
				map.set_cell(TILEMAP_LAYER, Vector2i(position.x + x, position.y + y), -1, Vector2i(0, 0))

func seal_exit(map: TileMap, pos: Vector2i, exit: Vector2i) -> void:
	var exit_pos = get_exit_pos(exit)
	var seal_tile_id = 0
	
	match exit:
		Vector2i.UP:
			map.set_cell(TILEMAP_LAYER, exit_pos + Vector2i(pos.x - 1, pos.y), seal_tile_id, Vector2i(0, 0))
			map.set_cell(TILEMAP_LAYER, exit_pos + Vector2i(pos.x, pos.y), seal_tile_id, Vector2i(0, 0))
			map.set_cell(TILEMAP_LAYER, exit_pos + Vector2i(pos.x + 1, pos.y), seal_tile_id, Vector2i(0, 0))
		Vector2i.DOWN:
			map.set_cell(TILEMAP_LAYER, exit_pos + Vector2i(pos.x - 1, pos.y), seal_tile_id, Vector2i(0, 0))
			map.set_cell(TILEMAP_LAYER, exit_pos + Vector2i(pos.x, pos.y), seal_tile_id, Vector2i(0, 0))
			map.set_cell(TILEMAP_LAYER, exit_pos + Vector2i(pos.x + 1, pos.y), seal_tile_id, Vector2i(0, 0))
		Vector2i.RIGHT:
			map.set_cell(TILEMAP_LAYER, exit_pos + Vector2i(pos.x, pos.y - 1), seal_tile_id, Vector2i(0, 0))
			map.set_cell(TILEMAP_LAYER, exit_pos + Vector2i(pos.x, pos.y), seal_tile_id, Vector2i(0, 0))
			map.set_cell(TILEMAP_LAYER, exit_pos + Vector2i(pos.x, pos.y + 1), seal_tile_id, Vector2i(0, 0))
		Vector2i.LEFT:
			map.set_cell(TILEMAP_LAYER, exit_pos + Vector2i(pos.x, pos.y - 1), seal_tile_id, Vector2i(0, 0))
			map.set_cell(TILEMAP_LAYER, exit_pos + Vector2i(pos.x, pos.y), seal_tile_id, Vector2i(0, 0))
			map.set_cell(TILEMAP_LAYER, exit_pos + Vector2i(pos.x, pos.y + 1), seal_tile_id, Vector2i(0, 0))

func is_overlapping(map: TileMap) -> bool:
	for x in range(0, self.room_size.x):
		for y in range(0, self.room_size.y):
			var tile = map.get_cell_source_id(TILEMAP_LAYER, Vector2i(self.position.x + x, self.position.y + y))
			if tile != -1:
				return true
	return false

# Validate room by checking that the top left tile is at 0, 0 and all exits are valid
func _validate() -> bool:

	# Check for tiles where x is negative
	pass
	
	# Check for tiles where y is negative
	pass
	
	# If exit on left, check that the middle tile on the left is empty
	if self.left and self.get_cell_source_id(TILEMAP_LAYER, Vector2i(0, self.room_size.y / 2)) != -1:
		push_error("Room with exit on left must have empty middle tile on left")
		return false
	# If exit on right, check that the middle tile on the right is empty
	if self.right and self.get_cell_source_id(TILEMAP_LAYER, Vector2i(self.room_size.x - 1, self.room_size.y / 2)) != -1:
		push_error("Room with exit on right must have empty middle tile on right")
		return false
	# If exit on top, check that the middle tile on the top is empty
	if self.top and self.get_cell_source_id(TILEMAP_LAYER, Vector2i(self.room_size.x / 2, 0)) != -1:
		push_error("Room with exit on top must have empty middle tile on top")
		return false
	# If exit on bottom, check that the middle tile on the bottom is empty
	if self.bottom and self.get_cell_source_id(TILEMAP_LAYER, Vector2i(self.room_size.x / 2, self.room_size.y - 1)) != -1:
		push_error("Room with exit on bottom must have empty middle tile on bottom")
		return false
	
	return true

func flip_vector(vector: Vector2i) -> Vector2i:
	return Vector2i(vector.x * -1, vector.y * -1)

func disable_room_exit_opposite(exit: Vector2i) -> void:
	self.disable_room_exit(self.flip_vector(exit))

func disable_room_exit(exit: Vector2i) -> void:
	if exit == Vector2i.LEFT:
		self.left = false
	elif exit == Vector2i.RIGHT:
		self.right = false
	elif exit == Vector2i.UP:
		self.top = false
	elif exit == Vector2i.DOWN:
		self.bottom = false
