#@icon("")
@tool
class_name ActManager extends Node

##ActManager里记录了一系列的ActID和对应的Act，主要用来同步场景的Act，比如，我们现在使用ActID = 0的Act，那么就会让所有的Act的状态重置回到ActID = 0的Act的状态
@export var prop_state_map: Dictionary[int, Act] = {}
##用于生成一个基础的Act的工具按钮
@export_tool_button("Generate Default Act")
var _gen_default_act: Callable = Callable(self, "_editor_generate_default_act")
##用于生成一个Empty的工具按钮
@export_tool_button("Generate Empty Act")
var _gen_empty_act: Callable = Callable(self, "_editor_generate_empty_act")
##是否要输出报错信息
@export var debug_log: bool = false
##关卡的初始Act，默认Clamp到Act的数量，防止出现错误，此处的-1是用来占位的，如果是 -1，意味着不修改，使用const的Id，即0
@export var init_act_id: int = -1:
	set(value):
		var max_index := max(prop_state_map.size() - 1, 0)
		init_act_id = clamp(value, 0, max_index)

## ====================
## Private Field
## ====================
var _current_act: Act = null
var _current_act_id: int = -1

const DEFAULT_ACT_ID:int = 0

signal act_changed(from_act_id: int, to_act_id: int)

func _ready() -> void:
	pass

##通过ID切换act
## 如果trans overwrite = 0，则使用act上自己配置的use trans
## 如果trans overwrite = 1，则全部禁用use trans
## 如果trans overwrite = 2，则全部开启use trans，注意，如果没有trans，则还是正常的切换
func switch_act_with_id(act_id: int,trans_overwrite: int = 0) -> void:
	if not prop_state_map.has(act_id):
		push_warning("[ActManager] Act id not found: %d" % act_id)
		return

	var act := prop_state_map[act_id]
	_switch_act_internal(act, act_id,trans_overwrite)

##内部通过ID和Act来切换状态
func _switch_act_internal(act: Act, act_id: int, trans_overwrite: int = 0) -> void:
	if act == null:
		return

	var from_id := _current_act_id

	_current_act = act
	_current_act_id = act_id

	for pid in act.prop_state_map.keys():
		var single : SingleAct = act.prop_state_map[pid]
		if single == null:
			continue

		var prop := _find_prop_by_id(pid)
		if prop == null:
			continue
		
		var use_trans: bool = false
		match trans_overwrite:
			0: use_trans = single.use_trans
			1: use_trans = false
			2: use_trans = true
		
		prop.change_state(single.state_id, use_trans)

	emit_signal("act_changed", from_id, act_id)

##用来扫描prop
func _scan_scene_for_props(scene_root: Node) -> Dictionary:
	var result := {}

	if scene_root == null:
		return result

	_scan_node_recursive(scene_root, result)
	return result


##递归扫描
func _scan_node_recursive(node: Node, out: Dictionary) -> void:
	if node is PropComponent:
		var prop := node as PropComponent
		if out.has(prop.prop_id):
			push_warning(
				"[ActManagerInspector] Duplicate prop_id: %d (%s)"
				% [prop.prop_id, node.get_path()]
			)
		else:
			out[prop.prop_id] = {
				"node": prop,
				"path": node.get_path()
			}

	for child in node.get_children():
		_scan_node_recursive(child, out)

##生成一个默认的Act
func _editor_generate_default_act() -> void:
	if not Engine.is_editor_hint():
		return

	var scene := _get_owner_scene()
	if scene == null:
		_editor_popup(
			"ActManager must be a child of ReedScene.",
			"Generate Default Act - Failed"
		)
		return

	var props_root := scene.get_props_root()
	if props_root == null:
		_editor_popup(
			"Props root not found:\n%s" % scene.props_root_path,
			"Generate Default Act - Failed"
		)
		return

	var act := Act.new()
	act.prop_state_map.clear()

	var count := 0

	for prop_node in props_root.get_children():
		if not prop_node is Node:
			continue

		var prop_comp := _find_prop_component_top(prop_node)
		if prop_comp == null:
			continue

		var pid := prop_comp.prop_id
		var init_state := prop_comp.initial_state_id

		var single := SingleAct.new()
		single.state_id = init_state

		act.prop_state_map[pid] = single
		count += 1

	prop_state_map[0] = act

	notify_property_list_changed()

	_editor_popup(
		"Default Act generated successfully.\n\nProp count: %d\nAct ID: 0" % count,
		"Generate Default Act - Success"
	)

	if debug_log:
		print("[ActManager][Editor] Generated Default Act with", count, "props.")

##生成一个空的Act
func _editor_generate_empty_act() -> void:
	if not Engine.is_editor_hint():
		return

	var act := Act.new()
	act.prop_state_map.clear() # 明确强调“空 Act”

	var act_id := _find_next_free_act_id()
	prop_state_map[act_id] = act

	notify_property_list_changed()

	_editor_popup(
		"Empty Act generated successfully.\n\nAct ID: %d\nProp count: 0" % act_id,
		"Generate Empty Act - Success"
	)

	if debug_log:
		print("[ActManager][Editor] Generated EMPTY Act with id =", act_id)

## ==============================
## 工具函数
## ==============================
func _editor_popup(message: String, title: String = "ActManager") -> void:
	if not Engine.is_editor_hint():
		return

	var dialog := AcceptDialog.new()
	dialog.title = title
	dialog.dialog_text = message
	get_tree().root.add_child(dialog)
	dialog.popup_centered()

##找到场景scene节点
func _get_owner_scene() -> ReedScene:
	var p := get_parent()
	if p is ReedScene:
		return p as ReedScene
	return null

##找到PropComp
func _find_prop_component_top(prop: Node) -> PropComponent:
	for child in prop.get_children():
		if child is PropComponent:
			return child as PropComponent
	return null

##找到最近的空位ActID
func _find_next_free_act_id() -> int:
	var id := 0
	while prop_state_map.has(id):
		id += 1
	return id

##通过ID寻找Prop
func _find_prop_by_id(prop_id: int) -> PropComponent:
	var scene := _get_owner_scene()
	if scene == null:
		return null

	var props_root := scene.get_props_root()
	if props_root == null:
		return null

	return _find_prop_recursive(props_root, prop_id)

##递归的寻找Prop
func _find_prop_recursive(node: Node, prop_id: int) -> PropComponent:
	if node is PropComponent and node.prop_id == prop_id:
		return node as PropComponent

	for child in node.get_children():
		var r := _find_prop_recursive(child, prop_id)
		if r != null:
			return r

	return null
