extends Spatial

signal prepared


# Declare member variables here. Examples:
# var a = 2
# var b = "text"


# Called when the node enters the scene tree for the first time.
var room = preload("res://scenes/maps/interior2.tscn")
var bed = preload("res://scenes/furniture/bed.tscn")
var table_chairs = preload("res://scenes/furniture/table_chairs.tscn")
var closet = preload("res://scenes/furniture/closet.tscn")
var size_x = 2
var size_y = 2
var floors = 2
var w = 10
var h = 8
var dungeon = []
var dungeon_save = {}
var spawn_save = {}
var prepared = false
var map = []
var exit_doors = []
var stairs_x = 0
var stairs_y = 0
func save():
	for k in range(dungeon.size()):
		dungeon[k].save()
		dungeon_save[str(k)] = dungeon[k].save_data
	global.save_data.dungeon = dungeon_save
var window_rooms = []
var doors = {}
func build_rooms():
	print("build_rooms")
	stairs_x = randi() % size_x
	stairs_y = randi() % size_y
	
	for k in range(floors):
		var cur_x = stairs_x
		var cur_y = stairs_y
		var cur_room = dungeon[k * size_x * size_y + cur_y * size_x + cur_x]
		cur_room.set_meta("stairs", k)
		var visited = []
		while cur_room:
			var choice = randi() % 4
			var sel = [cur_room.OPEN_LEFT, cur_room.OPEN_RIGHT, cur_room.OPEN_UP, cur_room.OPEN_DOWN]
			var rsel = [cur_room.OPEN_RIGHT, cur_room.OPEN_LEFT, cur_room.OPEN_DOWN, cur_room.OPEN_UP]
			var selx = [-1, 1, 0, 0]
			var sely = [0, 0, -1, 1]
			var nx = cur_x + selx[choice]
			var ny = cur_y + sely[choice]
			if nx >= 0 && nx < size_x && ny >= 0 && ny < size_y:
				cur_room.open_path(sel[choice])
				if !cur_room in visited:
					visited.push_back(cur_room)
				var old_room = cur_room
				cur_x = nx
				cur_y = ny
				cur_room = dungeon[k * size_x * size_y + cur_y * size_x + cur_x]
				cur_room.open_path(rsel[choice])
				if visited.size() == size_x * size_y:
					break
	print("base rooms done")
	for fl in range(floors):
		for k in range(size_x):
			var up = fl * size_x * size_y + k
			var down = fl * size_x * size_y + (size_y - 1) * size_x + k
			dungeon[up].open_window(dungeon[up].OPEN_UP)
			dungeon[down].open_window(dungeon[down].OPEN_DOWN)
			window_rooms.push_back(up)
			window_rooms.push_back(down)
		for k in range(size_y):
			var left = fl * size_x * size_y + k * size_x
			var right = fl * size_x * size_y + k * size_x + size_x - 1
			dungeon[left].open_window(dungeon[left].OPEN_LEFT)
			dungeon[right].open_window(dungeon[right].OPEN_RIGHT)
			window_rooms.push_back(left)
			window_rooms.push_back(right)

func build_exits():
	var street_exits = []
	while street_exits.size() == 0:
		var fl = 0
		for k in range(size_x):
			var up = fl * size_x * size_y + k
			var down = fl * size_x * size_y + (size_y - 1) * size_x + k
			for h in [up, down]:
				print(h)
				if street_exits.size() < 1:
					if dungeon[h].has_meta("master_room"):
						continue
					if randf() > 0.7:
						var d = dungeon[h].OPEN_UP if h == up else dungeon[h].OPEN_DOWN
						dungeon[h].outside_doors.push_back(d)
						dungeon[h].set_meta("exit_room", true)
						print("exit room: ", h)
						street_exits.push_back(h)
		for k in range(size_y):
			var left = fl * size_x * size_y + k * size_x
			var right = fl * size_x * size_y + k * size_x + size_x - 1
			for h in [left, right]:
				print(h)
				if street_exits.size() < 1:
					if dungeon[h].has_meta("master_room"):
						continue
					if randf() > 0.7:
						var d = dungeon[h].OPEN_LEFT if h == left else dungeon[h].OPEN_RIGHT
						dungeon[h].outside_doors.push_back(d)
						dungeon[h].set_meta("exit_room", true)
						print("exit room: ", h)
						street_exits.push_back(h)
	print("rooms build complete")
var special_rooms = {
	"master_room": {
		"alloc": floors * size_x * size_y
	},
	"jail_room": {
		"alloc": floors * size_x * size_y,
	},
	"kitchen_room": {
		"alloc": size_x * size_y
	}
}
func alloc_special_rooms():
	var allocated = []
	for e in range(floors):
		var id = e * size_x * size_y + stairs_y * size_x + stairs_x
		allocated.push_back(id)
		dungeon[id].set_meta("stairs", e)
	for k in special_rooms.keys():
		if special_rooms[k].has("id"):
			allocated.push_back(special_rooms[k].id)
	for k in special_rooms.keys():
		if special_rooms[k].has("id"):
			continue
		while true:
			var room_id = randi() % special_rooms[k].alloc
			if !room_id in allocated:
				special_rooms[k].id = room_id
				allocated.push_back(room_id)
				break
	for k in special_rooms.keys():
		var room_id = special_rooms[k].id
		dungeon[room_id].set_meta(k, true)
		if k == "master_room":
			var player_spawn = Spatial.new()
			dungeon[room_id].add_child(player_spawn)
			player_spawn.name = "player-spawn"
			player_spawn.add_to_group("spawn")
				
func build_special_rooms():
		print("build_special_rooms")
		alloc_special_rooms()

var state = 0
func _ready():
	pass
# Called every frame. 'delta' is the elapsed time since the previous frame.
var furniture_nodes = []
var dungeon_ids = []
func _process(_delta):
	match(state):
		0:
			global.save_data.dungeon_seed = OS.get_unix_time()
			global.load_game()
			seed(global.save_data.dungeon_seed)
			if global.save_data.has("dungeon"):
				dungeon_save = global.save_data.dungeon
				seed(global.save_data.dungeon_seed)
			state = 1
		1:
			dungeon.resize(floors * size_x * size_y)
			for k in range(floors):
				for i in range(size_x):
					for j in range(size_y):
						var ri = room.instance()
						add_child(ri)
						ri.translation.x = i * w - size_x / 2 * w
						ri.translation.y = 3.0 * float(k)
						ri.translation.z = j * h - size_y / 2 * h
						dungeon[k * size_x * size_y + j * size_x + i] = ri
			if dungeon_save.empty():
				state = 20
			else:
				state = 40
		20:
			print("build rooms")
			build_rooms()
			state = 21
		21:
			print("build special rooms")
			build_special_rooms()
			state = 31
		31:
			print("build exits")
			build_exits()
			state = 32
		32:
			print("build room nodes")
			for r in dungeon:
				r.create_rooms()
			exit_doors = get_tree().get_nodes_in_group("exit_door")
			state = 33
		33:
			print("spawn furniture")
			furniture_nodes = get_tree().get_nodes_in_group("furniture")
			state = 34
		34:
			if furniture_nodes.size() > 0:
				var k = furniture_nodes.pop_front()
				if k.name.begins_with("fc"):
					if randf() > 0.5 && !k.get_parent().has_meta("kitchen_room"):
						var bed_i = bed.instance()
						bed_i.set_meta("save_path", "res://scenes/furniture/bed.tscn")
						k.add_child(bed_i)
						k.rotate_y(randf() * PI / 8.0)
					elif !k.get_parent().has_meta("master_room") && !k.get_parent().has_meta("jail_room"):
						var table_i = table_chairs.instance()
						table_i.set_meta("save_path", "res://scenes/furniture/table_chairs.tscn")
						k.add_child(table_i)
						k.rotate_y(randf() * PI / 8.0)
				elif k.name.begins_with("fwb"):
					if !k.get_parent().has_meta("master_room") && !k.get_parent().has_meta("jail_room"):
						var closet_i = closet.instance()
						closet_i.set_meta("save_path", "res://scenes/furniture/closet.tscn")
						k.add_child(closet_i)
						k.rotate_y(randf() * PI / 24.0)
			else:
				save()
				state = 50
		40:
			dungeon_ids = range(dungeon.size())
			state = 41
		41:
			if dungeon_ids.size() > 0:
				var k = dungeon_ids.pop_front()
				dungeon[k].save_data = dungeon_save[str(k)]
				dungeon[k].restore()
			else:
				state = 50
		50:
			print("loaded")
			state = 60
			prepared = true
			emit_signal("prepared")
