extends Node2D
# Game orchestrator

signal round_won
signal arena_removed

export (String) var levelToLoop
export (Array, String) var levelNames = ["Square"]

var levelSceneToLoop
var levelScenes = []
var levelOldNode
var levelCurrentNode
var levelIndex = -1

var is_round_won

var _players_connected = false

onready var cam = $MainCamera
onready var start_timer = $StartTimer
onready var levelSwap = $LevelSwap
onready var hub = $Hub
onready var ui = $Ui


func _ready():
	# Prepare levels
	for _k in range(levelNames.size()):
		levelScenes.append(null)

	if levelToLoop:
		levelSceneToLoop = load_level(levelToLoop)
		if !levelSceneToLoop:
			push_error("Cant't load level " + levelToLoop)

	# Connections
	levelSwap.connect("tween_completed", self, "_on_swap_completed")
	hub.connect("hub_finished", self, "_on_hub_finished")


func _unhandled_input(event):
	if event.is_action("ui_accept") and event.is_pressed():
		if is_round_won:
			is_round_won = false
			create_game()
			get_tree().set_input_as_handled()


func connect_players():
	if _players_connected:
		push_error("Players are already connected!")
		return

	for player in get_tree().get_nodes_in_group("players"):

		start_timer.connect("timeout", player, "_on_round_start")
		self.connect("round_won", player, "_on_round_won")
		self.connect("arena_removed", player, "_on_arena_removed")

		player.connect("crash", self, "_on_player_crash")

		_players_connected = true


func load_level(name):
	var fullName = "res://Levels/" + name + ".tscn"
	return load(fullName)


func create_game():
	# Clear if required
	if levelCurrentNode:
		levelOldNode = levelCurrentNode

		levelSwap.swap_out(levelOldNode)
		emit_signal("arena_removed")

	# Create level node
	if levelToLoop:
		levelCurrentNode = levelSceneToLoop.instance()
	else:
		# Select next level
		levelIndex += 1

		if (levelIndex >= levelScenes.size()):
			levelIndex = 0
			levelScenes.shuffle()

		if !levelScenes[levelIndex]:
			levelScenes[levelIndex] = load_level(levelNames[levelIndex])

		levelCurrentNode = levelScenes[levelIndex].instance()

	# Put the level far away, the tween will bring it back
	levelCurrentNode.position.y = 2000

	# Manually spawn players for the first game
	if levelOldNode == null:
		# TODO : remove duplicated code with func _on_swap_completed
		add_child(levelCurrentNode)
		spawn_players()
		levelSwap.swap_in(levelCurrentNode)


func spawn_players():
	var spawners = get_tree().get_nodes_in_group("spawn")
	spawners.shuffle()

	var p = get_tree().get_nodes_in_group("players")

	for k in p.size():
		p[k].spawn(levelCurrentNode, spawners[k].position, spawners[k].rotation_degrees)


func _on_player_crash():
	if get_tree().get_nodes_in_group("running").size() <= 1 and !is_round_won:
		emit_signal("round_won")
		is_round_won = true


func _on_start_game():
	is_round_won = false


func _on_swap_completed(object, _k):
	if object == levelOldNode:
		remove_child(levelOldNode)
		levelOldNode.queue_free()
		levelOldNode = null

		add_child(levelCurrentNode)
		spawn_players()
		levelSwap.swap_in(levelCurrentNode)

	elif object == levelCurrentNode:
		start_timer.start()


func _on_hub_finished():
	connect_players()
	create_game()