extends Node3D
class_name Level

var barrels_amount = 0
var barrels_disposed = 0
var barrels_finished = false
var barrels_remaining = 0

var puddles_amount = 0
var puddles_cleaned = 0
var puddles_finished = false
var puddles_remaining = 0

var movables_list 

var game_scene
var debug_text_scene

signal all_barrels_disposed
signal all_puddles_cleaned
signal level_finished

func _init():
	add_to_group("level")
	#update_movable_list
	self.child_entered_tree.connect(Callable(self, "_on_child_entered_tree"))
	self.child_exiting_tree.connect(Callable(self, "_on_child_exited_tree"))
	
func _on_child_entered_tree(node: Node):
	if node.is_in_group("movable"):
		update_movable_list()

func _on_child_exited_tree(node: Node):
	if node.is_in_group("movable"):
		update_movable_list()
	
func update_movable_list():
	movables_list = get_tree().get_nodes_in_group("movable")

func _ready() -> void:
	
	game_scene = SceneManager.game_scene
	if game_scene != null:
		debug_text_scene = game_scene.debug_text_scene
	
	barrels_amount = get_tree().get_nodes_in_group("barrel").size()
	puddles_amount = get_tree().get_nodes_in_group("puddle").size()
	for barrel in get_tree().get_nodes_in_group("barrel"):
		barrel.barrel_disposed.connect(Callable(self, "_on_barrel_disposed"))
	for puddle in get_tree().get_nodes_in_group("puddle"):
		puddle.cleaned.connect(Callable(self, "_on_puddle_cleaned"))	
	
		
	update_movable_list()
	
	print ("barrels found: " + str(barrels_amount))
	print ("puddles found: " + str(puddles_amount))
	barrels_finished = !has_barrels()
	puddles_finished = !has_puddles()
	barrels_remaining = barrels_amount
	puddles_remaining = puddles_amount
	
	for n in get_children():
		if n.is_class("GridMap"):
			if n.position != Vector3(0, -1.6, 0):
				print ("WARNING: gridmap: " + str(n.name + " has bad positioning -  pos: " + str(n.position)))
				if debug_text_scene != null:
					debug_text_scene.show_debug_text("a gridmap is not aligned, see console output for details, that can lead to problems with the player and other movable objects not able to move")

func new_puddle_added():
	puddles_amount += 1
	puddles_remaining +=1
	if not SceneManager.game_scene:
		return
	SceneManager.game_scene.update_labels()
	print ("new puddle added")
	puddles_finished = false

func _on_puddle_cleaned() -> void:
	puddles_cleaned += 1
	print ("-- puddles cleaned: " + str(puddles_cleaned) + "/" + str(puddles_amount) + " --")
	puddles_remaining = puddles_amount - puddles_cleaned
	if puddles_cleaned == puddles_amount:
		emit_signal("all_barrels_disposed")
		puddles_finished = true
		check_all_goals()
	
	if not SceneManager.game_scene:
		return
	
	SceneManager.game_scene.update_labels()
	print(puddles_remaining)

func _on_barrel_disposed():
	barrels_disposed += 1
	print ("-- barrels disposed: " + str(barrels_disposed) + "/" + str(barrels_amount) + " --")
	barrels_remaining = barrels_amount - barrels_disposed
	if barrels_disposed == barrels_amount:
		emit_signal("all_puddles_cleaned")
		barrels_finished = true
		check_all_goals()
	print (SceneManager)
	if not SceneManager.game_scene:
		return
	SceneManager.game_scene.update_labels()
	
func has_barrels() -> bool:
	return barrels_amount > 0

func has_puddles() -> bool:
	return puddles_amount > 0
		
func check_all_goals():
	await get_tree().create_timer(0.1).timeout
	if barrels_finished and puddles_finished:
		print ("all finished")
		print(puddles_remaining)
		emit_signal("level_finished")


func is_target_free(movable: GridBasedMovable, target_pos: Vector3) -> bool:
	if movable == null:
		return true
	for mv in movables_list:
		if mv != null and movable != mv:
			if (target_pos - mv.target_position).length() < 0.5:
				return false
	return true

func find_object_at_position(movable: GridBasedMovable,  target_pos: Vector3):
	if movable == null:
		return null
	for mv in movables_list:	
		#print (mv)
		if mv != null and movable != mv:
			if (target_pos - mv.target_position).length() < 0.5:
				return mv
		
	return null	

