extends Node3D

const DIM_FACTOR := 0.5
const DIM_DURATION := 0.5
const WALL_DISPLAY_COLOR := Color(0.83, 0.63, 0.09)
const RobotScene := preload("res://scenes/robot.tscn")

@onready var _wall_display: Label3D = $ElevatorSafeZone/Elevator/WallDisplay
@onready var _hum: AudioStreamPlayer3D = $ElevatorSafeZone/Elevator/ElevatorHum
@onready var _robot_spawn: Marker3D = %RobotSpawn

var _dim_targets: Array = []
var _original_modulates: Array[Color] = []
var _modulate_tween: Tween = null
var _current_floor: int = EventBus.STARTING_FLOOR
var _robot: Node3D = null

func _ready() -> void:
	_collect_dim_targets()
	_wall_display.modulate = WALL_DISPLAY_COLOR
	_wall_display.text = str(_current_floor)
	EventBus.doors_closed.connect(_on_doors_closed)
	EventBus.doors_fully_closed.connect(_free_robot)
	EventBus.doors_opened.connect(_on_doors_opened)
	EventBus.floor_changed.connect(_on_floor_changed)
	EventBus.game_lost.connect(func(_reason: String): _free_robot())
	EventBus.game_won.connect(_free_robot)

func _collect_dim_targets() -> void:
	for path in [
		"ElevatorSafeZone/Elevator/ElevatorWallLeft/Wall",
		"ElevatorSafeZone/Elevator/ElevatorWallRight/Wall",
		"ElevatorSafeZone/Elevator/ElevatorDoorLeft/Panel",
		"ElevatorSafeZone/Elevator/ElevatorDoorRight/Panel",
	]:
		var node := get_node_or_null(path)
		if node and node is GeometryInstance3D:
			_dim_targets.append(node)
			_original_modulates.append(node.modulate)

func _on_doors_closed(_fast: bool) -> void:
	_tween_dim(DIM_FACTOR)
	if _hum.stream:
		_hum.play()
	var next_floor: int = max(1, _current_floor - 1)
	_wall_display.text = str(next_floor)

func _on_doors_opened() -> void:
	_tween_dim(1.0)
	_hum.stop()
	_spawn_robot()

func _spawn_robot() -> void:
	_free_robot()
	_robot = RobotScene.instantiate()
	_robot.position = _robot_spawn.position
	_robot.safety_zone = $ElevatorSafeZone
	add_child(_robot)

func _free_robot() -> void:
	if is_instance_valid(_robot):
		_robot.queue_free()
	_robot = null

func _on_floor_changed(new_floor: int) -> void:
	_current_floor = new_floor
	_wall_display.text = str(new_floor)

func _tween_dim(factor: float) -> void:
	if _modulate_tween:
		_modulate_tween.kill()
	_modulate_tween = create_tween()
	_modulate_tween.set_parallel(true)
	for i in _dim_targets.size():
		var node: GeometryInstance3D = _dim_targets[i]
		var base: Color = _original_modulates[i]
		var target := Color(base.r * factor, base.g * factor, base.b * factor, base.a)
		_modulate_tween.tween_property(node, "modulate", target, DIM_DURATION)
