local Event = require 'utils.event'
local Gui = require 'utils.gui'
local Server = require 'utils.server'
local SpamProtection = require 'utils.spam_protection'

local main_frame_name = Gui.uid_name()
local main_button_name = Gui.uid_name()
local discard_button_name = Gui.uid_name()
local instance_id_name = Gui.uid_name()
local insert = table.insert
local sort = table.sort

local function get_instance()
    local server_instances = Server.get_instances()
    local id = Server.get_server_id()
    if server_instances and server_instances[id] then
        return server_instances[id]
    else
        return { name = 'Offline', id = id, status = 'offline', version = script.active_mods.base }
    end
end

local function apply_button_style(button)
    local button_style = button.style
    button_style.font = 'default-semibold'
    button_style.height = 26
    button_style.minimal_width = 26
    button_style.top_padding = 0
    button_style.bottom_padding = 0
    button_style.left_padding = 2
    button_style.right_padding = 2
end

local function draw_main_frame(player)
    Gui.clear_all_active_frames(player)
    local instance = get_instance()

    local main_frame, inside_frame = Gui.add_main_frame_with_toolbar(player, 'left', main_frame_name, nil, discard_button_name, 'Comfy Servers')

    local inside_frame_style = inside_frame.style
    inside_frame_style.padding = 0
    inside_frame_style.maximal_height = 800

    player.opened = main_frame

    local instances = {}
    local server_instances = Server.get_instances()
    for _, i in pairs(server_instances) do
        insert(instances, i)
    end

    local viewer_table = inside_frame.add { type = 'table', column_count = 3 }
    viewer_table.style.cell_padding = 4

    sort(
        instances,
        function (a, b)
            return a.id < b.id
        end
    )

    if #instances <= 1 then
        viewer_table.add {
            type = 'label',
            caption = 'No other instances online'
        }
    else
        for _, i in ipairs(instances) do
            if string.len(i.name) > 1 then
                viewer_table.add {
                    type = 'label',
                    caption = i.name,
                    tooltip = i.connected .. '\nVersion: ' .. i.version,
                    style = 'caption_label'
                }
                local flow = viewer_table.add { type = 'flow' }
                flow.style.horizontal_align = 'right'
                flow.style.horizontally_stretchable = true
                local empty_flow = viewer_table.add { type = 'flow' }
                local button =
                    empty_flow.add {
                        type = 'button',
                        caption = 'Connect',
                        tooltip = 'Click to connect to this server.\n' .. i.connected .. '\nVersion: ' .. i.version,
                        name = instance_id_name
                    }
                Gui.set_data(button, i.id)
                apply_button_style(button)

                if i.id == instance.id then
                    button.enabled = false
                    button.tooltip = 'You are here'
                elseif i.status == 'unknown' then
                    button.enabled = i.game_port ~= nil
                    button.style.font_color = { r = 0.65 }
                    button.style.hovered_font_color = { r = 0.65 }
                    button.style.clicked_font_color = { r = 0.65 }
                    button.style.disabled_font_color = { r = 0.75, g = 0.1, b = 0.1 }
                    button.tooltip = 'Unknown status for this server'
                elseif i.status ~= 'running' then
                    button.enabled = false
                    button.tooltip = 'This server is offline'
                elseif i.version ~= instance.version then
                    button.enabled = false
                    button.tooltip = "We're on version: " .. instance.version .. '\nDestination server is on version: ' .. i.version
                end
            end
        end
    end
end

local function toggle(player)
    local left = player.gui.left
    local frame = left[main_frame_name]

    if not player or not player.valid or not player.character then
        return
    end

    if frame and frame.valid then
        Gui.remove_data_recursively(frame)
        frame.destroy()
    else
        draw_main_frame(player)
    end
end

local function create_main_button(event)
    local multiplayer = game.is_multiplayer()
    if not multiplayer then
        return
    end

    local player = game.get_player(event.player_index)
    if not player or not player.valid or not player.character then
        return
    end

    if Gui.get_mod_gui_top_frame() then
        local b =
            Gui.add_mod_button(
                player,
                {
                    type = 'sprite-button',
                    name = main_button_name,
                    sprite = 'utility/surface_editor_icon',
                    tooltip = 'Connect to another Comfy server!',
                    style = Gui.button_style
                }
            )
        if b then
            b.style.font_color = { 165, 165, 165 }
            b.style.font = 'default-semibold'
            b.style.minimal_height = 36
            b.style.maximal_height = 36
            b.style.minimal_width = 40
            b.style.padding = -2
        end
    else
        local main_button = player.gui.top[main_button_name]
        if not main_button or not main_button.valid then
            main_button =
                player.gui.top.add(
                    {
                        type = 'sprite-button',
                        sprite = 'utility/surface_editor_icon',
                        tooltip = 'Connect to another Comfy server!',
                        name = main_button_name,
                        style = Gui.button_style
                    }
                )
            main_button.style.font_color = { r = 0.11, g = 0.8, b = 0.44 }
            main_button.style.font = 'heading-1'
            main_button.style.minimal_height = 40
            main_button.style.maximal_width = 40
            main_button.style.minimal_width = 38
            main_button.style.maximal_height = 38
            main_button.style.padding = 1
            main_button.style.margin = 0
        end
    end
end

Gui.on_click(
    main_button_name,
    function (event)
        local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Server Select Main')
        if is_spamming then
            return
        end
        local player = event.player
        if not player or not player.valid or not player.character then
            return
        end
        toggle(player)
    end
)

Gui.on_click(
    discard_button_name,
    function (event)
        local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Server Select Discard')
        if is_spamming then
            return
        end
        local player = event.player
        if not player or not player.valid or not player.character then
            return
        end
        toggle(player)
    end
)

Gui.on_click(
    instance_id_name,
    function (event)
        local is_spamming = SpamProtection.is_spamming(event.player, nil, 'Server Select Connect')
        if is_spamming then
            return
        end
        local player = event.player
        if not player or not player.valid or not player.character then
            return
        end
        local id = Gui.get_data(event.element)
        local instance_id = tostring(id)
        local server_instances = Server.get_instances()
        local instance = server_instances[instance_id]

        if instance and instance.game_port and instance.public_address then
            player.connect_to_server {
                address = instance.public_address .. ':' .. instance.game_port,
                name = instance.name
            }
            toggle(player)
        end
    end
)

Event.add(defines.events.on_player_joined_game, create_main_button)
