@tool
# @singleton IconsFonts 
extends Node

const docked_setting_path := "application/addons/icon_finder/is_docked"
const prev_size_setting_path := "application/addons/icon_finder/preview_size"

## Material Icons
const material_icons_json := "res://addons/icons-fonts/icons_fonts/MaterialIcons/icons.json"
const material_icons_font := "res://addons/icons-fonts/icons_fonts/MaterialIcons/material_design_icons.ttf"

## Emojis
const emojis_json := "res://addons/icons-fonts/icons_fonts/emojis/emojis.json"
const emojis_font := "res://addons/icons-fonts/icons_fonts/emojis/NotoColorEmoji.ttf"

signal font_loaded(font_name: String)
var material_icons := {}
var emojis := {}

static var is_docked: bool:
	set(value):
		ProjectSettings.set_setting(docked_setting_path, value)
	get:
		return ProjectSettings.get_setting(docked_setting_path, true)

static var preview_size: int:
	set(value):
		ProjectSettings.set_setting(prev_size_setting_path, value)
	get:
		return ProjectSettings.get_setting(prev_size_setting_path, 24)

func _ready():
	var json: JSON
	var content: String
	if Engine.is_editor_hint():
		json = load(material_icons_json)
		init_material_icons_dict(json.data)
	else:
		json = JSON.new()
		content = get_file_content(material_icons_json)
		if json.parse(content) == OK:
			init_material_icons_dict(json.data)
	
	if Engine.is_editor_hint():
		json = load(emojis_json)
		init_emoji_dictionaries(json.data)
	else:
		json = JSON.new()
		content = get_file_content(emojis_json)
		if json.parse(content) == OK:
			init_emoji_dictionaries(json.data)
	
func get_file_content(path: String) -> String:
	var file := FileAccess.open(path, FileAccess.READ)
	var content := ""
	
	if file.get_error() == OK:
		content = file.get_as_text()
		file.close()

	return content

func init_material_icons_dict(data: Dictionary):
	material_icons = data
	for id in data:
		var hex = material_icons[id]
		material_icons[id] = ("0x" + hex).hex_to_int()
		# prints(id, material_icons[id])
	
	prints("FontsIcons: MaterialIcons loaded")
	font_loaded.emit("MaterialIcons")

func init_emoji_dictionaries(dict: Dictionary):
	for emoji in dict:
		var keys = dict[emoji]
		for key in keys:
			emojis[key] = emoji
		
	prints("FontsIcons: Emojis loaded")
	font_loaded.emit("Emojis")

func get_icon_code(font: String, id: String) -> int:
	if "," in id:
		id = id.split(",")[0]
	
	match font:
		"MaterialIcons":
			if id in material_icons:
				return material_icons[id]
	
	push_warning("Icon '%s' in font %s not found." % [id, font])
	return 0

func get_emoji_unicode(id: String) -> String:
	if id in emojis:
		# prints(id, emojis[id])
		return emojis[id]

	push_warning("Emoji %s not found." % id)
	return ""

func get_icon_char(font: String, id: String) -> String:
		match font:
			"MaterialIcons":
				return char(get_icon_code(font, id))
			
			"Emojis":
				return get_emoji_unicode(id)
		
		return ""

## will parse text using:
##	-  parse_material_icons()
##	-  parse_emojis()
##	-  parse_game_icons()
func parse_text(text: String) -> String:
	text = parse_material_icons(text)
	text = parse_emojis(text)
	# todo add game-icons parse
	return text

## will replace [mi:icon_name] with [font=MaterialIcons]icon_char[/font]
func parse_material_icons(text: String) -> String:
	var regex = RegEx.new()
	regex.compile("\\[mi:(.*?)\\]")
	var x = regex.search(text)
	while x != null:
		var icon = x.get_string(1)
		var char = get_icon_char("MaterialIcons", icon)
		var r = "[font={font}]{char}[/font]"
		r = r.format({"font": material_icons_font, "char": char})

		if icon.split(",").size() > 1:
			var size = icon.split(",")[1]
			var s = "[font_size={size}]{r}[/font_size]"
			r = s.format({"size": size, "r": r})

		text = text.replace(x.get_string(), r)
		x = regex.search(text)
	
	return text

func get_emoji_bbcode(id: String, size := 0) -> String:
	var emoji := get_icon_char("Emojis", id)
	if !emoji: return ""

	var bbcode := "[font=%s]%s[/font]" % [emojis_font, emoji]
	if size <= 0: return bbcode
	
	return "[font_size=%s]%s[/font_size]" % [size, bbcode]

## will replace :emoji_name: with [font=Emojis]emoji_char[/font]
func parse_emojis(text: String):
	var re = RegEx.new()
	re.compile(":[\\w\\d]+(,\\s*\\d+)?:")
	var result = re.search(text)
	while result != null:
		var temp := result.get_string()
		temp = temp.replace(":", "")
		var emoji := temp
		var size := 0

		if "," in temp:
			var splited := temp.split(",")
			emoji = splited[0]
			size = int(splited[1].replace(" ", ""))

		var replacement := get_emoji_bbcode(emoji, size)
		text = text.replace(result.get_string(), replacement)
		result = re.search(text)
	
	return text