extends Control

var node_data = {} #stores json file
@onready var parameter_container = $HBoxContainer/VBoxContainer2/ScrollContainer/parameter_container
var json = "res://scenes/main/process_help.json"

func _ready() -> void:
	Nodes.hide()
		
	load_json()
	
	
func load_json():
	var file = FileAccess.open(json, FileAccess.READ)
	if file:
		node_data = JSON.parse_string(file.get_as_text())
		
	fill_search("")


func fill_search(filter: String):
	# Remove all existing items from the VBoxContainer
	var container = $HBoxContainer/VBoxContainer/search/MarginContainer/VBoxContainer/ScrollContainer/ItemContainer
	for child in container.get_children():
		child.queue_free()
	for key in node_data.keys():
		var item = node_data[key]
		var title = item.get("title", "")
		
		var category = item.get("category", "")
		var subcategory = item.get("subcategory", "")
		var short_desc = item.get("short_description", "")
		
		# If filter is not empty, skip non-matches populate all other buttons
		if filter != "":
			var filter_lc = filter.to_lower()
			if not (filter_lc in title.to_lower() or filter_lc in short_desc.to_lower() or filter_lc in category.to_lower() or filter_lc in subcategory.to_lower()):
				continue
		
		
		var hbox = HBoxContainer.new()
		var label = RichTextLabel.new()
		var editbtn = Button.new()
		var margin = MarginContainer.new()
		
		hbox.size.x = container.size.x
		label.bbcode_enabled = true
		label.text = "[b]%s[/b]\n%s" % [title, short_desc]
		label.set_h_size_flags(Control.SIZE_EXPAND_FILL)
		label.set_v_size_flags(Control.SIZE_EXPAND_FILL)
		label.fit_content = true
		
		
		editbtn.text = "Edit"
		editbtn.custom_minimum_size = Vector2(80, 40)
		editbtn.set_h_size_flags(Control.SIZE_SHRINK_CENTER)
		editbtn.connect("pressed", Callable(self, "edit_node").bind(key)) #pass key (process name) when button is pressed
		
		margin.add_theme_constant_override("margin_bottom", 3)
		container.add_child(hbox)
		hbox.add_child(label)
		hbox.add_child(editbtn)
		container.add_child(margin)


func _on_search_bar_text_changed(new_text: String) -> void:
	fill_search(new_text)
	
func edit_node(key: String):
	if node_data.has(key):
		#looks up the help data from the json and stores it in info
		var info = node_data[key]
		var parameters = info.get("parameters", {})
		
		$HBoxContainer/VBoxContainer2/HBoxContainer/key.text = key
		$HBoxContainer/VBoxContainer2/HBoxContainer2/category.text = info.get("category", "")
		$HBoxContainer/VBoxContainer2/HBoxContainer3/subcategory.text = info.get("subcategory", "")
		$HBoxContainer/VBoxContainer2/HBoxContainer4/title.text = info.get("title", "")
		$HBoxContainer/VBoxContainer2/HBoxContainer5/shortdescription.text = info.get("short_description", "")
		$HBoxContainer/VBoxContainer2/HBoxContainer7/longdescription.text = info.get("description", "")
		$HBoxContainer/VBoxContainer2/HBoxContainer6/stereo.button_pressed = bool(info.get("stereo"))
		
		for child in parameter_container.get_children():
			child.queue_free()
			
		var count = 1
		for param_key in parameters.keys():
			var param_box = VBoxContainer.new()
			param_box.set_h_size_flags(Control.SIZE_EXPAND_FILL)
			parameter_container.add_child(param_box)
			
			var label = Label.new()
			label.text = "Parameter " + str(count)
			param_box.add_child(label)
			
			var param_data = parameters[param_key]
			
			for field_key in param_data.keys():
				var field_value = param_data[field_key]
				
				var hbox = HBoxContainer.new()
				var namelabel = RichTextLabel.new()
				var namefield

				
				namelabel.text = field_key
				namelabel.custom_minimum_size.x = 250
				
				if field_value is bool:
					namefield = CheckBox.new()
					namefield.button_pressed = field_value
				else:
					namefield = LineEdit.new()
					namefield.text = str(field_value)
					namefield.set_h_size_flags(Control.SIZE_EXPAND_FILL)
				
				hbox.add_child(namelabel)
				hbox.add_child(namefield)
				param_box.add_child(hbox)
			
			var delete_button = Button.new()
			delete_button.text = "Delete " + param_data.get("paramname", "")
			delete_button.set_h_size_flags(Control.SIZE_EXPAND)
			delete_button.connect("pressed", Callable(self, "delete_param").bind(param_box))
			param_box.add_child(delete_button)
			
			
			var margin = MarginContainer.new()
			margin.add_theme_constant_override("margin_bottom", 5)
			param_box.add_child(margin)
			
			count += 1
			
func delete_param(container: VBoxContainer):
	container.queue_free()




func _on_button_button_down() -> void:
	var info = node_data["distort_replace"]
	var parameters = info.get("parameters", {})
	var parameter = parameters.get("param1", {})
	
	var param_box = VBoxContainer.new()
	param_box.set_h_size_flags(Control.SIZE_EXPAND_FILL)
	parameter_container.add_child(param_box)
	
	var label = Label.new()
	label.text = "New Parameter"
	param_box.add_child(label)
	
	for field_key in parameter.keys():
		var field_value = parameter[field_key]
		
		var hbox = HBoxContainer.new()
		var namelabel = RichTextLabel.new()
		var namefield

		
		namelabel.text = field_key
		namelabel.custom_minimum_size.x = 250
		
		if field_value is bool:
			namefield = CheckBox.new()
		else:
			namefield = LineEdit.new()
			namefield.set_h_size_flags(Control.SIZE_EXPAND_FILL)
		
		hbox.add_child(namelabel)
		hbox.add_child(namefield)
		param_box.add_child(hbox)
	
	var delete_button = Button.new()
	delete_button.text = "Delete"
	delete_button.set_h_size_flags(Control.SIZE_EXPAND)
	delete_button.connect("pressed", Callable(self, "delete_param").bind(param_box))
	param_box.add_child(delete_button)
	
	
	var margin = MarginContainer.new()
	margin.add_theme_constant_override("margin_bottom", 5)
	param_box.add_child(margin)
	

func save_node(is_new: bool) -> void:
	var key = $HBoxContainer/VBoxContainer2/HBoxContainer/key.text.strip_edges()
	if key == "":
		printerr("Key is empty, cannot save")
		return

	var info = {
		"category": $HBoxContainer/VBoxContainer2/HBoxContainer2/category.text,
		"subcategory": $HBoxContainer/VBoxContainer2/HBoxContainer3/subcategory.text,
		"title": $HBoxContainer/VBoxContainer2/HBoxContainer4/title.text,
		"short_description": $HBoxContainer/VBoxContainer2/HBoxContainer5/shortdescription.text,
		"description": $HBoxContainer/VBoxContainer2/HBoxContainer7/longdescription.text,
		"stereo": $HBoxContainer/VBoxContainer2/HBoxContainer6/stereo.button_pressed,
		"parameters": {}
	}

	for param_box in parameter_container.get_children():
		var children = param_box.get_children()
		if children.size() < 2:
			continue

		var param_data = {}
		var param_label = children[0] as Label
		var param_id = "param" + str(parameter_container.get_children().find(param_box) + 1)

		for i in range(1, children.size()):
			var node = children[i]
			if node is HBoxContainer and node.get_child_count() >= 2:
				var field_name = node.get_child(0).text
				var input_field = node.get_child(1)
				var field_value

				if input_field is CheckBox:
					field_value = input_field.button_pressed
				else:
					var raw_text = input_field.text
					if raw_text.is_valid_float():
						field_value = raw_text.to_float()
					elif raw_text.is_valid_int():
						field_value = raw_text.to_int()
					elif raw_text.to_lower() == "true":
						field_value = true
					elif raw_text.to_lower() == "false":
						field_value = false
					else:
						field_value = raw_text

				param_data[field_name] = field_value

		if param_data.size() > 0:
			info["parameters"][param_id] = param_data

	# Save or update entry
	node_data[key] = info

	# Write to file
	var file = FileAccess.open(json, FileAccess.WRITE)
	if file:
		file.store_string(JSON.stringify(node_data, "\t"))  # pretty print with tab indent
		file.close()

	fill_search("")  # refresh list
	$HBoxContainer/VBoxContainer/search/MarginContainer/VBoxContainer/SearchBar.text = ""
	
	



func _on_save_changes_button_down() -> void:
	save_node(false)


func _on_save_new_button_down() -> void:
	save_node(true)


func _on_delete_process_button_down() -> void:
	var key = $HBoxContainer/VBoxContainer2/HBoxContainer/key.text.strip_edges()
	if key == "":
		printerr("No key entered – cannot delete.")
		return
	
	if not node_data.has(key):
		printerr("Key '%s' not found in JSON." % key)
		return

	# Remove entry from the dictionary
	node_data.erase(key)

	# Save updated JSON to file
	var file = FileAccess.open(json, FileAccess.WRITE)
	if file:
		file.store_string(JSON.stringify(node_data, "\t"))  # pretty print
		file.close()

	print("Deleted entry: ", key)

	# refresh the list
	fill_search("")
	$HBoxContainer/VBoxContainer/search/MarginContainer/VBoxContainer/SearchBar.text = ""
	_on_new_process_button_down()



func _on_new_process_button_down() -> void:
	$HBoxContainer/VBoxContainer2/HBoxContainer/key.text = ""
	$HBoxContainer/VBoxContainer2/HBoxContainer2/category.text = ""
	$HBoxContainer/VBoxContainer2/HBoxContainer3/subcategory.text = ""
	$HBoxContainer/VBoxContainer2/HBoxContainer4/title.text = ""
	$HBoxContainer/VBoxContainer2/HBoxContainer5/shortdescription.text = ""
	$HBoxContainer/VBoxContainer2/HBoxContainer7/longdescription.text = ""
	$HBoxContainer/VBoxContainer2/HBoxContainer6/stereo.button_pressed = false
	
	for child in parameter_container.get_children():
			child.queue_free()
	


func _on_sort_json_button_down() -> void:
	var json_to_sort = ProjectSettings.globalize_path(json)
	var python_script = ProjectSettings.globalize_path("res://dev_tools/helpers/sort_json.py")
	
	print(json_to_sort)
	print(python_script)

	# Run the Python script with the JSON path as an argument
	var output = []
	var exit_code = OS.execute("cmd.exe", ["/c", python_script, json_to_sort], output, true)

	# Optionally print the output or check the result
	print("Exit code: ", exit_code)
	print("Output:\n", output)
	
	fill_search("")  # refresh list
	$HBoxContainer/VBoxContainer/search/MarginContainer/VBoxContainer/SearchBar.text = ""
	
	load_json()
