extends Node3D
# this is basically the level manager

signal broadcast(command : String)
signal tick(time : int)

@export_group("Variables")
@export var level_tick : float = 1 # how often to run a command
@export var level_time : float = 10 # the amoutn of time allowed for the level
@export_multiline var level_name : String = "Level X\nTest Room"

#reset these
var tick_timer : float = 0 
var room_started : bool = false
var current_tick = 0
var failed : bool = false
var fail_timer : float = 2
var door_timer : float = 0

@export_group("Resources")
@export var pedestal_off_mat : Material
@export var pedestal_on_mat : Material
@export var pedestal_activated_cols : Array[Material]

@export_group("Node References")
@export var gui : Control
var pedestals : Array[Pedestal]
@export var pedstalContainer : Node3D
@export var chime_player : AudioStreamPlayer
@export var door_player :AudioStreamPlayer
@export var world_env : WorldEnvironment
@export var player : CharacterBody3D
@export var player_spawn : Node3D
@export var left_door : Node3D
@export var right_door : Node3D
@export var fail_sound_player : AudioStreamPlayer

# Called when the node enters the scene tree for the first time.
func _ready():
	tick.connect(gui.onTick)
	player.area.area_entered.connect(_player_area_entered)
	var temp_pedestals = pedstalContainer.get_children()
	for temp in temp_pedestals:
		pedestals.append(temp)
	for i in pedestals.size():
		pedestals[i].mesh.mesh = pedestals[i].mesh.mesh.duplicate()
	gui.show_level_title(level_name)


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	if(room_started):
		door_timer -= delta
	#-1.5 open, -0.5 closed
	left_door.position.x = -0.5 + clampf(door_timer*4, -0.995,0)
	right_door.position.x = 0.5 + clampf(-door_timer*4, 0,0.995)
	
	#if Input.is_action_just_pressed("debug_start"):
		#start_room()
	
	#if Input.is_action_just_pressed("interact"):
		#Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
	
	if Input.is_action_just_pressed("reset"):
		gui.show_lose_screen("Reset Pressed", 2)
		fail_room()
	
	if room_started and current_tick < level_time+1:
		tick_timer += delta
	
	if tick_timer > level_tick: #advance tick
		
		tick_timer = 0
		current_tick += 1
		if current_tick == 11:
			gui.show_lose_screen("Time Expired", 2)
			player.clear_effects()
			fail_room()
			pass
		print("Tick: " + str(current_tick))
		tick.emit(current_tick)
		for i in pedestals.size():
			if i+1 == current_tick: 
				var activated_pedestal = pedestals[i]
				#activated_pedestal.mesh.mesh.material = pedestal_on_mat
				activated_pedestal.mesh.mesh.material = pedestal_activated_cols[i]
				if activated_pedestal.has_command:
					print("broadcasting: " + activated_pedestal.placed_command.command_name)
					broadcast.emit(activated_pedestal.placed_command.command_name)
					chime_player.volume_db = -10
					chime_player.pitch_scale = 1
					chime_player.play()
				else:
					chime_player.volume_db = -20
					chime_player.pitch_scale = 0.5
					chime_player.play()
	
	if failed:
		gui.show_lose_screen("", fail_timer)
		world_env.environment.background_color = Color.DIM_GRAY
		fail_timer -= delta
		if(Input.is_action_just_pressed("reset") and fail_timer < 1.95):
			fail_timer = 0
		if fail_timer < 0:
			fail_timer = 2
			reset_room()
	else:
		world_env.environment.background_color = Color.WHITE
	
	
		
	if (player.global_position.y < -20):
		fail_room()
		gui.show_lose_screen("Fell out of world", 2)
		
	check_player_killzone()



func start_room():
	print("START")
	room_started = true
	
	# open door
	# start timers
	# start running commands
	#hide crosshair
	pass

func fail_room():
	print("ROOM FAILED")
	if not failed:
		fail_sound_player.play(18.0)
	room_started = false
	player.process_mode = Node.PROCESS_MODE_DISABLED
	failed = true
	# close exit, freeze player?
	pass

func reset_room():
	print("RESETTING ROOM")
	player.global_position = player_spawn.global_position
	player.process_mode = Node.PROCESS_MODE_INHERIT
	player.rotation_degrees = Vector3(0,0,0)
	player.camera.rotation_degrees = Vector3(0,0,0)
	
	gui.hide_lose_screen()
	
	tick_timer = 0 
	room_started = false
	current_tick = 0
	failed = false
	fail_timer = 2
	door_timer = 0
	
	#reset pedestals
	for i in pedestals.size(): 
		var activated_pedestal = pedestals[i]
		activated_pedestal.mesh.mesh.material = pedestal_off_mat
	# run if timer expires, resets puzzle
	# replace door
	# put player back in start room
	# reset timers
	
	player.clear_effects()
	gui.show_level_title(level_name)
	
	pass

func finish_room():
	# called when player reaches exit
	pass

func open_termimal():
	gui.terminal_panel.visible = true
	Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
	#display terminal ui
	pass


func _on_player_object_clicked(object):
	if(object.name == "StartButton"):
		if not room_started:
			door_player.play()
			start_room()
	if(object.name == "MenuButton"):
		get_tree().change_scene_to_file(GameManager.menu_scene_path)

func _player_area_entered(area : Area3D):
	#print(area.name)
	if "kill" in area:
		if not player.collider.disabled:
			fail_room()
			gui.show_lose_screen("Touched a reset block", 2)

func check_player_killzone():
	var hitbox : Area3D = player.area
	if(hitbox.get_overlapping_areas().size() > 0):
		for area in hitbox.get_overlapping_areas():
			if "kill" in area:
				if not player.collider.disabled:
					if(room_started):
						fail_room()
						gui.show_lose_screen("Touched a reset block", 2)

func pause():
	Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
	gui.open_pause()
	process_mode = Node.PROCESS_MODE_DISABLED
