class_name ChatMenu
extends Control


#region Onready Variables

@onready var scroll_container = $AspectRatioContainer/MarginContainer/VBoxContainer/ScrollContainer
@onready var command_text_edit = $AspectRatioContainer/MarginContainer/VBoxContainer/CommandScrollContainer/CommandTextEdit
@onready var message_container = $AspectRatioContainer/MarginContainer/VBoxContainer/ScrollContainer/MessageContainer
@onready var visible_timer     = $VisibleTimer

#endregion


#region Variables

var opened             : bool = false
var clear_command_text : bool = false

#endregion


#region Signals

signal chat_opened()
signal spawn_item(item_name : String, x : String, y : String, z : String)
signal lobby_move(x : String, z : String)

#endregion


#region Godot Functions

func _ready() -> void:
    hide()
    opened = false
    command_text_edit.gui_input.connect(_command_text_edit_gui_input)
    visible_timer.timeout.connect(hide)

func _process(_delta : float):
    if clear_command_text == true:
        command_text_edit.text = ""
        clear_command_text = false

    if opened == true:
        if Input.is_action_just_pressed("pause"):
            remove_focus()
            visible_timer.start()
        return

    if Input.is_action_just_pressed("open_chat"):
        visible_timer.stop()
        chat_opened.emit()
        show()
        focus()

    if Input.is_action_just_pressed("open_chat_as_command"):
        visible_timer.stop()
        command_text_edit.text = "/"
        chat_opened.emit()
        show()
        focus()
        command_text_edit.set_caret_column(1, false, 0)

#endregion


#region Public Functions

func focus():
    mouse_filter = Control.MOUSE_FILTER_STOP
    opened = true
    Global.in_menu = true
    command_text_edit.grab_focus()

func remove_focus():
    mouse_filter = Control.MOUSE_FILTER_IGNORE
    opened = false
    command_text_edit.release_focus()
    Global.in_menu = false

func send_message(message : String, keep_focus : bool, label_color : Color = Color(1, 1, 1, 1)):
    visible_timer.stop()
    show()
    var message_label : Label = Label.new()
    message_label.text = message
    message_label.label_settings = LabelSettings.new()
    message_label.label_settings.font_color = label_color
    message_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
    message_container.add_child(message_label)

    if keep_focus == false:
        remove_focus()
        visible_timer.start()

    get_tree().create_timer(0.01).timeout.connect(
        func() -> void:
            scroll_container.scroll_vertical = scroll_container.get_v_scroll_bar().max_value
    )

#endregion


#region Signal Functions

func _command_text_edit_gui_input(event : InputEvent):
    if event.is_action_pressed("chat_send"):
        send_message(command_text_edit.text, false)
        check_command(command_text_edit.text)
        clear_command_text = true

#endregion


#region "Private" Functions

func check_command(command : String):
    command.strip_edges(true, true)

    if command.begins_with("/") == false:
        return

    if Global.is_admin == false:
        send_message("Cannot run command without admin status", false)
        return

    command = command.lstrip("/")

    # ~ SPAWN ~ #
    if command.begins_with("spawn ") or command == "spawn":
        command = command.lstrip("spawn ")
        command = command.trim_prefix(" ")

        #get the item name and check that it exists
        var item_next_space : int = command.find(" ")
        if item_next_space == -1:
            send_message("Spawn Syntax error, spawn command looks like `spawn <entity_name> x y z`", false, Color(1, 0, 0, 1))
            return

        var item_name : String = command.substr(0, item_next_space)
        command = command.lstrip(item_name)
        command = command.trim_prefix(" ")

        # if EntityResource.ids_by_name.has(item_name) == false:
        #     var entity_names = ""
        #     for key in EntityResource.data:
        #         if EntityResource.data[key].spawnable == false:
        #             continue

        #         entity_names += EntityResource.data[key].name + " "

            # send_message("Entity: \"" + item_name + "\" was not found, cannot spawn. Entity List is: " + entity_names, false, Color(1, 0, 0, 1))
            # return

        #get x
        item_next_space = command.find(" ")
        if item_next_space == -1:
            send_message("Spawn Syntax error, spawn command looks like `spawn <entity_name> x y z`", false, Color(1, 0, 0, 1))
            return

        var x_name : String = command.substr(0, item_next_space)
        command = command.lstrip(x_name)
        command = command.trim_prefix(" ")

        if x_name != "~" and x_name.is_valid_int() == false:
            send_message("Spawn Syntax error: x value was not ~ or int", false, Color(1, 0, 0, 1))
            return

        #get y
        item_next_space = command.find(" ")
        if item_next_space == -1:
            send_message("Spawn Syntax error, spawn command looks like `spawn <entity_name> x y z`", false, Color(1, 0, 0, 1))
            return

        var y_name : String = command.substr(0, item_next_space)
        command = command.lstrip(y_name)
        command = command.trim_prefix(" ")

        if y_name != "~" and y_name.is_valid_int() == false:
            send_message("Spawn Syntax error: y value was not ~ or int", false, Color(1, 0, 0, 1))
            return

        #check z (which is what is left in command)
        command = command.trim_prefix(" ")
        command = command.trim_suffix(" ")
        if command == "":
            send_message("Spawn Syntax error, spawn command looks like `spawn <entity_name> x y z`", false, Color(1, 0, 0, 1))

        if command != "~" and command.is_valid_int() == false:
            send_message("Item Spawn Syntax error: z value was not ~ or int", false, Color(1, 0, 0, 1))
            return

        #call spawn item
        spawn_item.emit(item_name, x_name, y_name, command)
        return

    # ~ LOBBY ~ #
    if command.begins_with("lobby ") or command == "lobby":
        command = command.lstrip("lobby ")
        command = command.trim_prefix(" ")

        #get the type name and check that it exists
        var type_next_space : int = command.find(" ")
        if type_next_space == -1:
            send_message("Lobby Syntax error, lobby command looks like `lobby <action> [args]`", false, Color(1, 0, 0, 1))
            return

        # ~ move ~ #
        if command.begins_with("move ") or command == "move":
            command = command.lstrip("move ")
            command = command.trim_prefix(" ")

            #error check for if there is no position
            if command == "":
                send_message("Lobby Move Syntax error, lobby move command looks like `lobby move x z`", false, Color(1, 0, 0, 1))
                return

            #get x
            var position_space : int = command.find(" ")
            if position_space == -1:
                send_message("Lobby Move Syntax error, lobby move command looks like `lobby move x z`", false, Color(1, 0, 0, 1))
                return

            var x_name : String = command.substr(0, position_space)
            command = command.lstrip(x_name)
            command = command.trim_prefix(" ")

            if x_name != "~" and x_name.is_valid_int() == false:
                send_message("Lobby Move Syntax error: x value was not ~ or int", false, Color(1, 0, 0, 1))
                return

            #check z (which is what is left in command)
            command = command.trim_prefix(" ")
            command = command.trim_suffix(" ")
            if command == "":
                send_message("Lobby Move Syntax error, lobby move command looks like `lobby move x z`", false, Color(1, 0, 0, 1))

            if command != "~" and command.is_valid_int() == false:
                send_message("Lobby Move Syntax error: z value was not ~ or int", false, Color(1, 0, 0, 1))
                return

            #call spawn item
            lobby_move.emit(x_name, command)
            return

#endregion
