extends VBoxContainer

signal on_select_change(avatar_type: String, index: int, state_code: String)

@onready var button_0: Button = $MarginContainer/VBoxContainer/HBoxContainer2/Button0
@onready var button_1: Button = $MarginContainer/VBoxContainer/HBoxContainer2/Button1
@onready var button_2: Button = $MarginContainer/VBoxContainer/HBoxContainer2/Button2
@onready var button_3: Button = $MarginContainer/VBoxContainer/HBoxContainer2/Button3
@onready var button_collapse: Button = $MarginContainer/VBoxContainer/HBoxContainer2/ButtonCollapse
@onready var button_expand: Button = $MarginContainer/VBoxContainer/HBoxContainer2/ButtonExpand

@onready var state_name_label: Label = $MarginContainer/VBoxContainer/StateNameLabel
@onready var state_treeview: Tree = $MarginContainer/VBoxContainer/StateTreeview

var avatar_type: String = "Clothes"

var current_avatar_part = null
var current_avatar_index = 0
var current_tree_item: TreeItem = null
var current_state_code = ""
var state_map = {}
var icon_checked:Texture2D
var icon_warning:Texture2D
var filter_type = 0
var tree_max_depth = 0
var item_collection = {}


func _ready() -> void:
	_init_gui()

func _process(_delta: float) -> void:
	pass

func _init_gui():
	icon_checked = load("res://Resources/UI/checked.png")
	icon_warning = load("res://Resources/UI/warning.png")
	
	state_treeview.columns = 3
	state_treeview.hide_root = true
	state_treeview.set_column_custom_minimum_width(1, 60)
	state_treeview.set_column_custom_minimum_width(2, 16)
	state_treeview.set_column_expand(0, true)
	state_treeview.set_column_expand(1, false)
	state_treeview.set_column_expand(2, false)
	state_treeview.item_selected.connect(_on_state_treeview_item_selected)
	state_treeview.item_activated.connect(_on_state_treeview_item_activated)
	state_treeview.create_item()
	
	var group = ButtonGroup.new()
	var buttons = [button_0, button_1, button_2, button_3]
	for i in range(buttons.size()):
		var button = buttons[i]
		button.button_group = group
		button.pressed.connect(_on_filter_button_pressed.bind(i))
	
	button_collapse.pressed.connect(_on_button_collapse_pressed)
	button_expand.pressed.connect(_on_button_expand_pressed)

func set_avatar_type(index, rebuild_tree: bool):
	current_avatar_index = index
	if current_avatar_index >= 0 and AvatarDollDataMgr.avatar_doll_data[avatar_type].size() > index:
		current_avatar_part = AvatarDollDataMgr.avatar_doll_data[avatar_type][index]
	update_data(rebuild_tree)

func set_state_code(state_code):
	var item = state_treeview.get_root()
	for c in state_code:
		var index = AvatarDollDataMgr.get_state_index(c)
		item = item.get_child(index)
		if item == null:
			return
	state_treeview.set_selected(item, 0)
	state_treeview.scroll_to_item(item)
	_on_state_treeview_item_selected()

func update_data(rebuild_tree: bool = false):
	if not AvatarDollDataMgr.initialed or avatar_type not in AvatarDollDataMgr.avatar_doll_data:
		state_treeview.clear()
		state_treeview.create_item() # root
		return
		
	#var old_index = current_avatar_index
	#var old_state = current_state_code
	
	var states = AvatarDollDataMgr.avatar_part_state[avatar_type]
	var root
	if rebuild_tree:
		state_treeview.clear()
		root = state_treeview.create_item()
		item_collection = {}
		if current_avatar_index >= 0:
			tree_max_depth = states.size()
			for i in range(tree_max_depth):
				item_collection[i] = []
			_add_state_item(rebuild_tree, states, root)
			
	else:
		root = state_treeview.get_root()
		if current_avatar_index >= 0:
			_add_state_item(rebuild_tree, states, root)
	
func _add_state_item(rebuild_tree, states: Array, parent: TreeItem, depth = 0, current_list = ["R"], state_code=""):
	if depth >= states.size():
		var state_name = "/".join(current_list)
		var setup = current_avatar_part["Elements"].get(state_code, []).size() > 0
		var requirment = current_list[0] == "R"
		
		if setup:
			parent.set_icon(2, icon_checked)
		elif requirment:
			parent.set_icon(2, icon_warning)
		else:
			parent.set_icon(2, null)
		
		if (filter_type == 1 and not setup) or \
				(filter_type == 2 and not requirment) or \
				(filter_type == 3 and not (requirment and not setup)):
			parent.visible = false
		else:
			parent.visible = true	
			
		parent.set_metadata(0, state_name)
		parent.set_metadata(1, state_code)
		parent.set_metadata(2, Vector3i(1 if setup else 0, 1 if requirment else 0, 1))
		parent.set_custom_color(0, Color.WHITE)
		
	else:
		var state = states[depth]
		var state_count = state["Values"].size()
		var item
		for i in range(state_count):
			var value = state["Values"][i]
			
			if rebuild_tree:
				item = parent.create_child()
				item_collection[depth].append(item)
			else:
				item = parent.get_child(i)
			
			var c = AvatarDollDataMgr.get_state_char(i)
			item.set_text(0, "%s %s" % [c, value])
			item.set_cell_mode(2, TreeItem.CELL_MODE_ICON)
			
			var new_list = current_list + [value]
			var new_code = state_code + c
			
			if state["Required"][i] == false: 
				new_list[0] = "N"
				
			_add_state_item(rebuild_tree, states, item, depth + 1, new_list, new_code)
		
		var parent_visible = false
		var total = Vector3i.ZERO
		var missing = false
		for child in parent.get_children():
			if child.visible == true:
				parent_visible = true
			if child.get_icon(2) == icon_warning:
				missing = true
			total += child.get_metadata(2)
				
		parent.visible = parent_visible
		parent.set_text(1, "%d/%d/%d" % [total.x, total.y, total.z])
		parent.set_text_alignment(1, HORIZONTAL_ALIGNMENT_RIGHT)
		parent.set_icon(2, icon_warning if missing else icon_checked)
		parent.set_metadata(2, total)
		parent.set_custom_color(0, Color(0.6, 0.6, 0.6))
			
func _on_filter_button_pressed(index):
	filter_type = index
	update_data()

func _on_state_treeview_item_selected():
	var item = state_treeview.get_selected()
	var state_name = item.get_metadata(0)
	var state_code = item.get_metadata(1)
	
	if state_code != null:
		var parent
		if current_tree_item != null:
			current_tree_item.clear_custom_bg_color(0)
			current_tree_item.clear_custom_bg_color(1)
			current_tree_item.clear_custom_bg_color(2)
			parent = current_tree_item.get_parent()
			while parent != state_treeview.get_root():
				parent.clear_custom_bg_color(0)
				parent.clear_custom_bg_color(1)
				parent.clear_custom_bg_color(2)
				parent = parent.get_parent()
			
		var color = Color(0.0, 0.6, 0.8, 1.0)
		item.set_custom_bg_color(0, color)
		item.set_custom_bg_color(1, color)
		item.set_custom_bg_color(2, color)
		
		color = Color(0.0, 0.3, 0.4, 1.0)
		parent = item.get_parent()
		while parent != state_treeview.get_root():
			parent.set_custom_bg_color(0, color)
			parent.set_custom_bg_color(1, color)
			parent.set_custom_bg_color(2, color)
			parent = parent.get_parent()
			
		current_tree_item = item
		current_state_code = state_code
		state_name_label.text = "%s %s" % [state_code, state_name.substr(2)]
		on_select_change.emit(avatar_type, current_avatar_index, state_code)
		print("State: ", state_name, " ", state_code)
	pass

func _on_state_treeview_item_activated():
	var item = state_treeview.get_selected()
	var state_code = item.get_metadata(1)
	if state_code == null:
		item.collapsed = not item.collapsed
	
func _on_button_collapse_pressed():
	if not AvatarDollDataMgr.initialed:
		return
		
	var result = _collect_tree_item_collapse_and_expand(state_treeview.get_root(), tree_max_depth - 1)
	var max_expand = result[1]
	
	while max_expand < tree_max_depth:
		for item in item_collection[max_expand - 1]:
			item.collapsed = true
		max_expand += 1 
	
func _on_button_expand_pressed():
	if not AvatarDollDataMgr.initialed:
		return
	var result = _collect_tree_item_collapse_and_expand(state_treeview.get_root(), tree_max_depth - 1)
	var min_collapse = result[0]
	
	while min_collapse > 0:
		for item in item_collection[min_collapse - 1]:
			item.collapsed = false
		min_collapse -= 1 

func _collect_tree_item_collapse_and_expand(parent: TreeItem, min_collapse:int = 9999, max_expand:int = 1, depth = 0):
	if parent.get_child_count() == 0:
		return [9999, 0]
	
	var all_collapsed = false
	for item in parent.get_children():
		if item.collapsed:
			min_collapse = min(min_collapse, depth + 1)
		else:
			all_collapsed = false
			var result = _collect_tree_item_collapse_and_expand(item, min_collapse, depth + 1, depth + 1)
			min_collapse = min(min_collapse, result[0])
			max_expand = max(max_expand, result[1])
	
	if all_collapsed:
		return [min_collapse, depth]
	else:
		return [min_collapse, max_expand]
