extends Control

@onready var avatar_type_combo: OptionButton = $VBoxContainer/HSplitContainer/VSplitContainer/PanelContainer/MarginContainer/VBoxContainer/AvatarTypeCombo
@onready var avatar_part_listview: Tree = $VBoxContainer/HSplitContainer/VSplitContainer/PanelContainer/MarginContainer/VBoxContainer/AvatarPartListview
@onready var palette_listview: Tree = $VBoxContainer/HSplitContainer/VSplitContainer/PanelContainer2/MarginContainer2/VBoxContainer/PaletteListview
@onready var main_content_tab_container: TabBar = $VBoxContainer/HSplitContainer/HSplitContainer/VSplitContainer/VBoxContainer/PanelContainer2/MainContentTabContainer
@onready var state_selecter: PanelContainer = $VBoxContainer/HSplitContainer/HSplitContainer/VSplitContainer/StateSelecter

@onready var palette_param_container: VBoxContainer = $VBoxContainer/HSplitContainer/HSplitContainer/VSplitContainer2/PanelContainer2/MarginContainer/VBoxContainer/ScrollContainer/ParamVBoxContainer
@onready var palette_add_button: Button  = $VBoxContainer/HSplitContainer/VSplitContainer/PanelContainer2/MarginContainer2/VBoxContainer/HBoxContainer/Add
@onready var palette_param_add_button: Button = $VBoxContainer/HSplitContainer/HSplitContainer/VSplitContainer2/PanelContainer2/MarginContainer/VBoxContainer/HBoxContainer/Add
@onready var canvas_2d: Node2D = $VBoxContainer/HSplitContainer/HSplitContainer/VSplitContainer/VBoxContainer/PanelContainer/SubViewportContainer/SubViewport/Canvas2d

@onready var guid_line_edit: LineEdit = $VBoxContainer/HSplitContainer/HSplitContainer/VSplitContainer2/PanelContainer/MarginContainer/VBoxContainer/GridContainer/GuidLineEdit
@onready var name_line_edit: LineEdit = $VBoxContainer/HSplitContainer/HSplitContainer/VSplitContainer2/PanelContainer/MarginContainer/VBoxContainer/GridContainer/NameLineEdit
@onready var intro_text_edit: TextEdit = $VBoxContainer/HSplitContainer/HSplitContainer/VSplitContainer2/PanelContainer/MarginContainer/VBoxContainer/GridContainer/IntroTextEdit

const PALETTE_PARAM_PANEL = preload("res://Scenes/control/PaletteParamPanel.tscn")
const MAX_PALETTE_PARAM_PANEL = 8

var palette_param_panels = []
var palette_param_panel_data = []
var palette_param_count = 0

var camera_zoom_texture = 100
var camera_position_texture = Vector2.ZERO
var camera_zoom_icon = 100
var camera_position_icon = Vector2.ZERO

var _current_avatar_type = "Clothes"
var _current_avatar_index = -1
var _current_part
var _current_palette_index = -1
var _current_part_assets = {}
var _current_state_code = null

func _ready() -> void:
	_init_gui()

func _init_gui():
	canvas_2d.set_editable(false)
	visibility_changed.connect(_on_visibility_changed)
	avatar_type_combo.item_selected.connect(_on_avatar_type_combo_item_selected)
	main_content_tab_container.tab_changed.connect(_on_main_content_tab_container_tab_changed)
	state_selecter.state_selected.connect(_on_state_selected)
	
	# avatar_part
	avatar_part_listview.columns = 2
	avatar_part_listview.hide_root = true
	avatar_part_listview.set_column_title(0, "ID")
	avatar_part_listview.set_column_title(1, "Name")
	avatar_part_listview.set_column_custom_minimum_width(0, 40)
	avatar_part_listview.set_column_expand(1, true)
	avatar_part_listview.set_column_expand_ratio(1, 3)
	avatar_part_listview.item_selected.connect(_on_avatar_part_listview_item_selected)
	
	# palette
	palette_add_button.pressed.connect(_on_palette_add_button_preessed)
	palette_listview.columns = 2
	palette_listview.hide_root = true
	palette_listview.set_column_title(0, "ID")
	palette_listview.set_column_title(1, "Name")
	palette_listview.set_column_custom_minimum_width(0, 40)
	palette_listview.set_column_expand(1, true)
	palette_listview.set_column_expand_ratio(1, 3)
	palette_listview.item_selected.connect(_on_palette_listview_item_selected)

	# palette_param
	palette_param_add_button.pressed.connect(_on_palette_param_add_button_preessed)
	for i in range(MAX_PALETTE_PARAM_PANEL):
		var param_panel = PALETTE_PARAM_PANEL.instantiate()
		param_panel.name = "palette_param_%d" % i
		param_panel.visible = false

		palette_param_panel_data.append({})
		palette_param_panels.append(param_panel)
		palette_param_container.add_child(param_panel)
		
		param_panel.reset_parameters()
		param_panel.value_change.connect(_on_palette_param_panel_value_change)
		param_panel.action.connect(_on_palette_param_panel_action)
		
	# palette property
	name_line_edit.text_submitted.connect(_on_name_line_edit_text_submitted)
	intro_text_edit.text_submitted.connect(_on_intro_text_edit_text_submitted)
	
func load_data():
	if AvatarDollDataMgr.initialed == false:
		return
	update_avatar_part_listview()

func update_avatar_part_listview():
	if AvatarDollDataMgr.initialed == false:
		return
	
	_current_part = null
	_current_part_assets = {}
	_current_avatar_index = -1
	_current_state_code = null
	
	avatar_part_listview.clear()
	avatar_part_listview.create_item()  # root
	
	var _data = AvatarDollDataMgr.avatar_doll_data
	if not _data.has(_current_avatar_type):
		return
		
	for i in _data[_current_avatar_type].size():
		var part = _data[_current_avatar_type][i]
		var row = avatar_part_listview.create_item()
		row.set_text(0, "%d" % i)
		row.set_text(1, part["Name"])
	
func update_state_selecter(select_code = null):
	if AvatarDollDataMgr.initialed == false or _current_part == null:
		_current_state_code = null
		state_selecter.load_data(null)
		return
		
	_current_state_code = null
	state_selecter.load_data(_current_avatar_type, _current_part)
	
	if select_code in _current_part["Elements"]:
		_current_state_code = select_code
		state_selecter.set_state_list_select(_current_state_code)
	elif _current_part["Elements"].size() > 0:
		_current_state_code = _current_part["Elements"].keys()[0]
		state_selecter.set_state_list_select(_current_state_code)

func update_palette_listview(selected_index = -1):
	if AvatarDollDataMgr.initialed == false or _current_part == null or _current_state_code == null:
		_current_part_assets = {}
		return
	
	# palette_listview
	palette_listview.clear()
	palette_listview.create_item() # root
	
	var row = palette_listview.create_item() # default
	row.set_text(0, "-1")
	row.set_text(1, "Default")
	
	for i in _current_part["Palettes"].size():
		var palette = _current_part["Palettes"][i]
		row = palette_listview.create_item()
		row.set_text(0, "%d" % i)
		row.set_text(1, palette["Name"])

	# finish
	if selected_index < _current_part["Palettes"].size():
		_current_palette_index = selected_index
		for item in palette_listview.get_root().get_children():
			if selected_index == int(item.get_text(0)):
				palette_listview.set_selected(item, 0)
	else:
		_current_palette_index = -1
		palette_listview.set_selected(palette_listview.get_root().get_child(0), 0)
	
func update_palette_property():
	if AvatarDollDataMgr.initialed == false or _current_part == null or _current_state_code == null:
		return
		
	if _current_palette_index < 0:
		guid_line_edit.text = str(_current_palette_index)
		name_line_edit.text = _current_part["Name"]
		intro_text_edit.text = _current_part["Introduction"]
	else:
		guid_line_edit.text = str(_current_palette_index)
		name_line_edit.text = _current_part["Palettes"][_current_palette_index]["Name"]
		intro_text_edit.text = _current_part["Palettes"][_current_palette_index]["Introduction"]

func update_palette_param():
	if AvatarDollDataMgr.initialed == false or _current_part == null or _current_state_code == null:
		return
		
	# set enable
	var palette_param = []
	if _current_palette_index < 0: 
		palette_param_count = 0
		palette_param_add_button.disabled = true
	else:
		palette_param = get_current_palette_param_list()
		palette_param_count = min(MAX_PALETTE_PARAM_PANEL, palette_param.size())
		palette_param_add_button.disabled = false
	
	# update asset combo
	var assets = {}
	assets[-1] = "All"
	if main_content_tab_container.current_tab == 0:
		var elements = _current_part["Elements"][_current_state_code]
		for i in elements.size():
			var asset_name = AvatarDollDataMgr.get_asset_name(elements[i]["AssetId"])
			if asset_name != "__blank__":
				assets[i] = asset_name
		_current_part_assets = assets
	
	for i in range(MAX_PALETTE_PARAM_PANEL):
		var param_panel = palette_param_panels[i]
		param_panel.set_block_signal(true)
		param_panel.setup_data(i, _current_part_assets, i==0, i == palette_param_count - 1)
		param_panel.set_block_signal(false)
		param_panel.visible = false
		
	# set param
	for i in range(MAX_PALETTE_PARAM_PANEL):
		var param_panel = palette_param_panels[i]
		if i < palette_param_count:
			param_panel.visible = true
			var param = palette_param[i]
			var basic_color = Color(param["BasicColor"]["R"], param["BasicColor"]["G"], param["BasicColor"]["B"], param["BasicColor"]["A"])
			var modulate_color = Color(param["ModulateColor"]["R"], param["ModulateColor"]["G"], param["ModulateColor"]["B"], param["ModulateColor"]["A"])
			palette_param_panel_data[i] = param
			
			param_panel.set_block_signal(true)
			param_panel.load_parameters(param["ElementIndex"], basic_color, param["Tolerance"], modulate_color, int(param["BlendMode"]))
			param_panel.set_block_signal(false)
			
		else:
			param_panel.visible = false
	
	update_canvas()

func get_current_palette_param_list():
	if _current_palette_index == -1 or _current_part == null:
		return []
		
	var color_palette = _current_part["Palettes"][_current_palette_index]
	if main_content_tab_container.current_tab == 0:
		return color_palette["ElementPaletteParam"]
	else:
		return color_palette["IconPaletteParam"]

func update_canvas():
	if AvatarDollDataMgr.initialed == false or _current_part == null or _current_state_code == null:
		canvas_2d.load_elements([])
		canvas_2d.zoom_fit()
		return
	
	if main_content_tab_container.current_tab == 0:
		var palettes = AvatarDollDataMgr.get_render_palettes(
			_current_avatar_type, 
			_current_avatar_index, 
			_current_state_code, 
			_current_palette_index, 
			false)
		
		var elements = _current_part["Elements"][_current_state_code]
		canvas_2d.load_elements(elements)
		
		for element_index in palettes:
			canvas_2d.update_palette(element_index, palettes[element_index])
	else:
		canvas_2d.load_icon(_current_part["IconAssetId"])
		canvas_2d.update_palette(0, get_current_palette_param_list())
	
	canvas_2d.queue_redraw()

func _on_visibility_changed() -> void:
	if is_visible_in_tree() == true:
		update_state_selecter(_current_state_code)
		update_palette_listview(_current_palette_index)
		update_palette_property()
		update_palette_param()
		update_canvas()
		canvas_2d.sync_background()
	else:
		canvas_2d.cancle_free_transform()

func _on_avatar_type_combo_item_selected(_index: int) -> void:
	_current_avatar_type = avatar_type_combo.get_item_text(avatar_type_combo.selected)
	update_avatar_part_listview()
	
	canvas_2d.load_elements([])
	canvas_2d.zoom_fit()

func _on_avatar_part_listview_item_selected():
	_current_avatar_index = int(avatar_part_listview.get_selected().get_text(0))
	_current_part = AvatarDollDataMgr.avatar_doll_data[_current_avatar_type][_current_avatar_index]
	update_state_selecter(_current_state_code)
	update_palette_listview()
	update_canvas()
	canvas_2d.zoom_fit()
	
func _on_palette_add_button_preessed():
	pass
	
func _on_palette_listview_item_selected():
	var index = int(palette_listview.get_selected().get_text(0))
	_current_palette_index = index
	update_palette_property()
	update_palette_param()
	update_canvas()

func _on_main_content_tab_container_tab_changed(new_index: int):
	update_palette_listview(_current_palette_index)
	
	if new_index == 0:
		state_selecter.visible = true
		camera_position_icon = canvas_2d.camera.position
		camera_zoom_icon = canvas_2d.current_zoom
		canvas_2d.zoom_camera(camera_zoom_texture)
		canvas_2d.camera.position = camera_position_texture
		canvas_2d.set_background(Vector2(2048, 2048))
	else:
		state_selecter.visible = false
		
		camera_position_texture = canvas_2d.camera.position
		camera_zoom_texture = canvas_2d.current_zoom
		canvas_2d.zoom_camera(camera_zoom_icon)
		canvas_2d.camera.position = camera_position_icon
		canvas_2d.set_background(Vector2(64, 64))
		
	update_canvas()

func _on_palette_param_panel_action(index, action):
	match action:
		"UP":
			var palette_param = get_current_palette_param_list()
			var t = palette_param[index - 1]
			palette_param[index - 1] = palette_param[index]
			palette_param[index] = t
			update_palette_param()
			
		"DOWN":
			var palette_param = get_current_palette_param_list()
			var t = palette_param[index + 1]
			palette_param[index + 1] = palette_param[index]
			palette_param[index] = t
			update_palette_param()
			
		"REMOVE":
			var msg_box = MessageBox.warning(self, "警告", "确定删除吗？", MessageBox.StandardButton.YES | MessageBox.StandardButton.NO)
			msg_box.accepted.connect(func(): 
				var palette_param = get_current_palette_param_list()
				palette_param.remove_at(index)
				update_palette_param()	
			)

func _on_palette_param_add_button_preessed():
	if not AvatarDollDataMgr.initialed or palette_param_count >= MAX_PALETTE_PARAM_PANEL:
		return
		
	var panel = palette_param_panels[palette_param_count]
	var palette_param = get_current_palette_param_list()
	palette_param.append(panel.get_paramters())
	panel.reset_parameters()
	
	palette_param_count += 1
	for i in range(MAX_PALETTE_PARAM_PANEL):
		panel = palette_param_panels[i]
		if i < palette_param_count:
			panel.visible = true
		else:
			panel.visible = false
	palette_param_panels[palette_param_count - 1].set_selected(true)
	
func _on_palette_param_panel_value_change(index: int, data):
	var palette_param = get_current_palette_param_list()
	palette_param[index] = data
	update_canvas()

func _on_state_selected(state_code: String):
	_current_state_code = state_code
	update_palette_param()
	update_canvas()

func _on_name_line_edit_text_submitted(new_text):
	pass
	
func _on_intro_text_edit_text_submitted(new_text):
	pass
	
