    tool
    class_name CodeSnapshotInstance
    extends Control

    onready var viewport_container : ViewportContainer = $VSplitContainer/ViewportContainer
    onready var viewport : Viewport = viewport_container.get_child(0)
    onready var snapshot_container : ColorRect = viewport.get_node("Background")
    onready var settings_container : VBoxContainer = $VSplitContainer/Settings

    onready var script_container : PanelContainer = snapshot_container.get_node("ScriptContainer")
    onready var script_edit : TextEdit = script_container.get_node("VBox/ScriptEdit")
    onready var template_menu : PopupMenu = settings_container.get_node("Template/TemplateMenu").get_popup()
    onready var colors_list : VBoxContainer = settings_container.get_node("Colors/ColorsList")
    onready var properties_list : VBoxContainer = settings_container.get_node("Properties/PropertiesList")
    onready var from : LineEdit = settings_container.get_node("Properties/PropertiesList/from_line_to_line/from")
    onready var to : LineEdit = settings_container.get_node("Properties/PropertiesList/from_line_to_line/to")
    onready var save : FileDialog = $Save

    var script_editor : ScriptEditor
    var editor_settings : EditorSettings

    var template_dir : String = "res://addons/code-snapshot/godot-syntax-themes/"
    var templates : PoolStringArray
    var template_file : String = "Darcula"

    var keywords : Array = ["self", "if", "else", "elif", "or", "and", "yield","func", "onready", "export", "var", "tool", "extends", "void", "null", "true", "false", "class_name", "print", "return", "pass", "match", "in", "define", "const"]
    var types : PoolStringArray = ClassDB.get_class_list()
    var from_line_to : Array = [-1, -1]
    var lines_count_as_min_size : bool = true
    var exporting_extension : String
    var path_to_save : String

    func set_editor_settings(settings : EditorSettings):
    	editor_settings = settings

    func set_script_editor(editor : ScriptEditor):
    	script_editor = editor
    	script_editor.connect("editor_script_changed", self, "_on_script_changed")
    	_on_script_changed(script_editor.get_current_script())

    func hide_nodes():
    	colors_list.hide()
    	properties_list.hide()

    func _ready() -> void:
    	yield(get_tree(),"idle_frame")
    #	viewport.set_process_input(true)
    	script_edit.set_text("")
    	template_menu.connect("index_pressed", self, "_on_index_pressed")
    	hide_nodes()
    	load_templates()
    	if script_editor != null : _on_script_changed(script_editor.get_current_script())

    func load_templates():
    	templates = []
    	template_menu.clear()
    	var dir = Directory.new()
    	if dir.open(template_dir) == OK:
    		dir.list_dir_begin()
    		var file_name = dir.get_next()
    		while file_name != "":
    			if not dir.current_is_dir() and file_name.get_extension() == "tet":
    				templates.append(file_name.get_basename())
    				template_menu.add_item(file_name.get_basename())
    			file_name = dir.get_next()
    	else:
    			print("An error occurred when trying to access the path.")
    	_on_index_pressed(0)

    func _on_index_pressed(index : int):
    	apply_template(templates[index])
    	$VSplitContainer/Settings/Template/TemplateMenu.set_text("> "+templates[index])

    func apply_template(template : String):
    	var config = ConfigFile.new()
    	var err = config.load(template_dir+"%s.tet"%template)
    	if err == OK: # If not, something went wrong with the file loading
    		set_script_box_color(config.get_value("color_theme", "background_color"))
    		for setting in config.get_section_keys("color_theme"):
    			if setting == "gdscript/function_definition_color" :
    				add_function_definition_color(config.get_value("color_theme",setting))
    				set_node_color("function_definition_color", config, "gdscript/")
    			if setting == "keyword_color": add_keywords_color(config.get_value("color_theme",setting))
    			if setting == "comment_color": add_comment_color(config.get_value("color_theme", setting))
    			if setting == "string_color" : add_string_color(config.get_value("color_theme", setting))
    			if setting == "engine_type_color" : add_engine_type_color(config.get_value("color_theme",setting))
    			if setting == "gdscript/node_path_color" : add_node_path_color(config.get_value("color_theme",setting))
    			if setting == "text_color" : set_text_color(config.get_value("color_theme",setting))
    			script_edit.set("custom_colors/"+setting, config.get_value("color_theme",setting))
    			set_node_color(setting, config)

    func set_node_color(setting : String, config : ConfigFile, category : String = ""):
    	if colors_list.get_node_or_null("%s/Color"%setting) != null : colors_list.get_node_or_null("%s/Color"%setting).color = config.get_value("color_theme",category+setting)

    func add_node_path_color(color : Color):
    	script_edit.add_color_region("$","", color, false)

    func add_engine_type_color(color : Color):
    	for type in types: script_edit.add_keyword_color(type, color)

    func add_function_definition_color(color : Color):
    	script_edit.add_color_region("func ","", color)

    func set_script_edit_size(size : Vector2):
    	script_container.rect_size = size

    func set_background_color(color : Color):
    	snapshot_container.color = color

    # Script Box Color
    func set_script_box_color(color : Color):
    	script_container.get("custom_styles/panel").set("bg_color", color)
    	set_script_background_color(color)

    func get_script_box_color() -> String:
    	return "#"+script_container.get("custom_styles/panel").get("bg_color").to_html(false)
    # ................

    func set_member_variable_color(color : Color):
    	script_edit.set("custom_colors/member_variable_color", color)

    func set_function_color(color : Color):
    	script_edit.set("custom_colors/function_color", color)

    # Script Background color .....
    func set_script_background_color(color : Color):
    	script_edit.set("custom_colors/background_color", color)

    func get_script_background_color() -> String:
    	return "#"+script_edit.get("custom_colors/background_color").to_html(false)
    # ..............

    func set_number_color(color : Color):
    	script_edit.set("custom_colors/number_color", color)

    # Text Color .....
    func set_text_color(color : Color):
    	script_edit.set("custom_colors/font_color", color)

    func get_text_color() -> String:
    	return "#"+script_edit.get("custom_colors/font_color").to_html(false)
    # ................

    func add_keywords_color(color : Color):
    	for keyword in keywords:
    		script_edit.add_keyword_color(keyword,color)

    func add_comment_color(color : Color):
    	script_edit.add_color_region("#","",color,true)

    func add_string_color(color : Color):
    	script_edit.add_color_region('"','"',color,false)

    func set_from_line_to(from : int, to : int):
    	from_line_to = [from, to]

    var current_script : Script

    func _on_script_changed(script : Script):
    	if script == null or script_edit == null: return
    	current_script = script
    	var code : String = script.get_source_code()
    	var code_array : Array = code.c_unescape().split("
    ")
    	code = PoolStringArray(code_array.slice(from_line_to[0]-1 if from_line_to[0] != -1 and from_line_to[0] < code_array.size()-1 else 0, from_line_to[1]-1 if from_line_to[1] != -1 and from_line_to[1] < code_array.size()-1 else code_array.size()-1)).join("
    ")
    	script_edit.set_text(code)
    	change_frame_min_size()

    func change_frame_min_size():
    	if lines_count_as_min_size:
    		script_edit.rect_min_size.y = script_edit.get_line_count() * (editor_settings.get_setting("interface/editor/code_font_size") + 6) if script_edit.get_line_count() <= 35 else 132
    		viewport_container.rect_min_size.y = script_edit.rect_min_size.y + 168
    	else:
    		script_edit.rect_min_size.y = 0
    		viewport_container.rect_min_size.y = 300

    func _on_ColorsBtn_toggled(button_pressed : bool):
    	colors_list.visible = button_pressed
    	if button_pressed: $VSplitContainer/Settings/Colors/ColorsBtn.set_text("v Colors")
    	else: $VSplitContainer/Settings/Colors/ColorsBtn.set_text("> Colors")

    func _on_PropertiesBtn_toggled(button_pressed : bool):
    	properties_list.visible = button_pressed
    	if button_pressed: $VSplitContainer/Settings/Properties/PropertiesBtn.set_text("v Properties")
    	else: $VSplitContainer/Settings/Properties/PropertiesBtn.set_text("> Properties")

    func _on_export_confirmed(path : String):
    	path_to_save = path

    func _on_Save_hide():
    	match exporting_extension:
    		"png":
    			var image : Image = viewport.get_texture().get_data()
    			image.flip_y()
    			image.save_png(path_to_save)
    		"html":
    			var file : File = File.new()
    			file.open(path_to_save, File.WRITE)
    			var content : String = '
    '
    			content+='

    '
    			content+=script_edit.text+"
    "
    			content+='
    '
    			file.store_line(content)
    			file.close()

    func _on_autowrap_value_toggled(button_pressed):
    	script_edit.wrap_enabled = button_pressed
    	script_edit.update()

    func _on_draw_tabs_value_toggled(button_pressed):
    	script_edit.draw_tabs = button_pressed

    func _on_from_text_changed(new_text):
    	if new_text.is_valid_integer():
    		if int(new_text) == 0:
    			new_text = str(-1)
    			from.set_text(new_text)
    		from_line_to[0] = int(new_text)
    		_on_script_changed(current_script)

    func _on_to_text_changed(new_text):
    	if new_text.is_valid_integer():
    		if int(new_text) == 0:
    			new_text = str(-1)
    			to.set_text(new_text)
    		from_line_to[1] = int(new_text)
    		_on_script_changed(current_script)

    func _on_Reload_pressed():
    	_on_script_changed(current_script)

    func _on_minimap_draw_value_toggled(button_pressed):
    	script_edit.minimap_draw = button_pressed

    func _on_ViewportContainer_item_rect_changed():
    	snapshot_container.rect_size = viewport_container.rect_size

    func _on_minsie_value_toggled(button_pressed):
    	lines_count_as_min_size = button_pressed
    	change_frame_min_size()

    func _on_ExportPNG_pressed():
    	exporting_extension = "png"
    	save.filters = ["*.png ; Portable Network Graphics"]
    	save.current_file = "snapshot.png"
    	save.popup()

    func _on_ExportHTML_pressed():
    	exporting_extension = "html"
    	save.filters = ["*.html ; HyperText Markup Language"]
    	save.current_file = "snapshot.html"
    	save.popup()