-- Garry's Mod Binder - Main Server Logic
include("binder/sh_lang.lua")
include("binder/core/sh_config.lua")

util.AddNetworkString("Binder_SyncProfiles")
util.AddNetworkString("Binder_UpdateProfile")
util.AddNetworkString("Binder_DeleteProfile")
util.AddNetworkString("Binder_SetActiveProfile")

Binder = Binder or {}
Binder.Profiles = Binder.Profiles or {}

-- Default structure
-- Profile = { Name = "Profile1", Binds = { [KEY_X] = "cmd" }, Radial = { [1] = { Label = "L", Cmd = "cmd" } }, Active = true }

function Binder.SaveProfiles(ply)
    local data = util.TableToJSON(Binder.Profiles[ply:SteamID64()] or {})
    ply:SetPData("Binder_Profiles", data)
end

function Binder.LoadProfiles(ply)
    local data = ply:GetPData("Binder_Profiles", "[]")
    local profiles = Binder.SanitizeProfiles(util.JSONToTable(data) or {})
    
    -- Ensure at least one default profile if empty
    if table.Count(profiles) == 0 then
        table.insert(profiles, {
            Name = Binder.GetPhrase("raiding_profile"),
            Binds = {},
            Radial = {},
            Active = true
        })
    end

    Binder.Profiles[ply:SteamID64()] = profiles
    
    -- Sync to client
    net.Start("Binder_SyncProfiles")
        local compressed = util.Compress(util.TableToJSON(profiles))
        net.WriteUInt(#compressed, 32)
        net.WriteData(compressed, #compressed)
    net.Send(ply)
end

hook.Add("PlayerInitialSpawn", "Binder_LoadOnSpawn", function(ply)
    Binder.LoadProfiles(ply)
end)

-- Receive entire profile updates from client (e.g., binds changed)
net.Receive("Binder_UpdateProfile", function(len, ply)
    local length = net.ReadUInt(32)
    local compressed = net.ReadData(length)
    local data = util.Decompress(compressed)
    
    if data then
        local profiles = Binder.SanitizeProfiles(util.JSONToTable(data) or {})
        if profiles then
            Binder.Profiles[ply:SteamID64()] = profiles
            Binder.SaveProfiles(ply)
        end
    end
end)

-- Chat Command to open the Binder
hook.Add("PlayerSay", "Binder_ChatCommand", function(ply, text, teamTalk)
    local lowerText = string.lower(text)
    if string.sub(lowerText, 1, 5) == "/bind" or string.sub(lowerText, 1, 5) == "!bind" then
        ply:ConCommand("binder_menu")
        return "" -- Hide the command from chat
    end
end)