class_name DebugMenu extends CanvasLayer

signal close_requested

var active_scene_container: Node

var scene_registry: Array = [
	{ "name": "Battle Test", "path": "res://scenes/views/battle_view.tscn" },
	{ "name": "Main Menu", "path": "res://scenes/views/main_menu_view.tscn" },
	{ "name": "Dialogue Test", "path": "res://scenes/dialogue_scene.tscn" },
	{ "name": "Test Scene", "path": "res://scenes/test_scene.tscn" },
]

var commands: Array[ConsoleCommand] = []

@onready var panel: PanelContainer = %Panel
@onready var scene_list: VBoxContainer = %SceneList
@onready var command_input: LineEdit = %CommandInput
@onready var result_label: Label = %ResultLabel

func _ready() -> void:
	commands = [
		HelpCommand.new(),
		ListScenesCommand.new(),
		SwapCommand.new(),
	]
	_build_scene_buttons()
	command_input.text_submitted.connect(_on_command_submitted)
	result_label.text = ""

func _build_scene_buttons() -> void:
	for child in scene_list.get_children():
		child.queue_free()
	for entry: Dictionary in scene_registry:
		var button := Button.new()
		button.text = entry["name"]
		button.pressed.connect(swap_scene.bind(entry))
		scene_list.add_child(button)

func swap_scene(entry: Dictionary) -> void:
	for child in active_scene_container.get_children():
		active_scene_container.remove_child(child)
		child.queue_free()
	var scene: PackedScene = load(entry["path"])
	var instance := scene.instantiate()
	active_scene_container.add_child(instance)
	if entry.has("setup"):
		_apply_setup(entry["setup"], instance)
	close_requested.emit()

func _apply_setup(setup_key: String, _scene_instance: Node) -> void:
	match setup_key:
		_:
			push_warning("Unknown setup key: %s" % setup_key)

func _on_command_submitted(text: String) -> void:
	command_input.text = ""
	if text.strip_edges().is_empty():
		return
	var result := _execute_command(text.strip_edges())
	_show_result(result)

func _execute_command(input: String) -> String:
	var parts := input.split(" ", false)
	var command_name := parts[0]
	var args: Array = []
	if parts.size() > 1:
		args = Array(parts.slice(1))

	var context := {
		"commands": commands,
		"scene_registry": scene_registry,
		"debug_menu": self,
		"active_scene_container": active_scene_container,
	}

	for command: ConsoleCommand in commands:
		if command.get_command_name() == command_name:
			return command.run(args, context)

	return _eval_expression(input)

func _eval_expression(input: String) -> String:
	var expression := Expression.new()
	var error := expression.parse(input)
	if error != OK:
		return "Parse error: %s" % expression.get_error_text()

	var active_scene: Node = null
	if active_scene_container.get_child_count() > 0:
		active_scene = active_scene_container.get_child(0)

	var result = expression.execute([], active_scene)
	if expression.has_execute_failed():
		return "Error: %s" % expression.get_error_text()

	return str(result)

func _show_result(text: String) -> void:
	result_label.text = text
#	if _result_tween and _result_tween.is_valid():
#		_result_tween.kill()
#	_result_tween = create_tween()
#	_result_tween.tween_interval(2.0)
#	_result_tween.tween_callback(func(): result_label.text = "")
