local E=game:GetService("\080\108\097\121\101\114\115")local Y=script:FindFirstAncestor("\067\109\100\114\065\100\100\105\116\105\111\110\115")local O=Y.Packages local x=Y.Shared local L=require(O.Promise)local a=require(x.GroupController)local p={}p.__index=p function p.new(Y)local O=setmetatable({CmdrAdditions=Y,Controller=a.new(Y.Config),_groups={}},p)E.PlayerAdded:Connect(function(E)O._groups[E]=O.Controller:GetDefaultGroup();((O:_resolvePlayerGroup(E)):andThen(function(Y)if Y then O._groups[E]=Y end end)):catch(function(Y)warn(("\091\099\109\100\114-\097\100\100\105\116\105\111\110\115\093 \070\097\105\108\101\100 \116\111 \103\101\116 \112\101\114\109\105\115\115\105\111\110 \103\114\111\117\112 \102\111\114 \037\115\058"):format(E.Name))warn(Y)end)end)E.PlayerRemoving:Connect(function(E)O._groups[E]=nil end)Y.Network:SetRequestHandler("\071\101\116\071\114\111\117\112",function(E)return O._groups[E]end)return O end function p._resolvePlayerGroup(Y,E)local O={}for Y,x in pairs(Y.CmdrAdditions.Config.GroupGetters)do table.insert(O,(L.promisify(x))(E))end return(L.all(O)):andThen(function(E)local O for E,x in pairs(E)do local L=Y.Controller.Groups[x]if not O or L.Index<O.Index then O=L end end return O.Name end)end function p.GetPlayerGroup(Y,E)return Y._groups[E]or Y.Controller:GetDefaultGroup()end function p.SetPlayerGroup(O,E,Y)if E:IsDescendantOf(game)then O._groups[E]=Y O.CmdrAdditions.Network:SendEvent(E,"\085\112\100\097\116\101\071\114\111\117\112",Y)end end function p.CanPlayerRunCommand(O,E,Y)local x=O:GetPlayerGroup(E)return O.Controller:CanGroupRunCommand(x,Y)end function p.SetRegistry(Y,E)Y.Controller:SetRegistry(E)end return p
local Players = game:GetService("Players")

local Root = script:FindFirstAncestor("CmdrAdditions")
local Packages = Root.Packages
local Shared = Root.Shared

local Promise = require(Packages.Promise)

local GroupController = require(Shared.GroupController)

local PermissionsServer = {}
PermissionsServer.__index = PermissionsServer

function PermissionsServer.new(cmdrAdditions)
	local self = setmetatable({
		CmdrAdditions = cmdrAdditions,
		Controller = GroupController.new(cmdrAdditions.Config),
		_groups = {}
	}, PermissionsServer)

	Players.PlayerAdded:Connect(function(player)
		self._groups[player] = self.Controller:GetDefaultGroup()

		self:_resolvePlayerGroup(player):andThen(function(groupName)
			if groupName then
				self._groups[player] = groupName
			end
		end):catch(function(error)
			warn(("[cmdr-additions] Failed to get permission group for %s:"):format(player.Name))
			warn(error)
		end)
	end)

	Players.PlayerRemoving:Connect(function(player)
		self._groups[player] = nil
	end)

	cmdrAdditions.Network:SetRequestHandler("GetGroup", function(player)
		return self._groups[player]
	end)
	
	return self
end

function PermissionsServer:_resolvePlayerGroup(player)
	local promises = {}

	for _, getter in pairs(self.CmdrAdditions.Config.GroupGetters) do
		table.insert(promises, Promise.promisify(getter)(player))
	end

	return Promise.all(promises):andThen(function(groups)
		local targetGroup

		for _, groupName in pairs(groups) do
			local group = self.Controller.Groups[groupName]
			if not targetGroup or group.Index < targetGroup.Index then
				targetGroup = group
			end
		end

		return targetGroup.Name
	end)
end

function PermissionsServer:GetPlayerGroup(player)
	return self._groups[player] or self.Controller:GetDefaultGroup()
end

function PermissionsServer:SetPlayerGroup(player, groupName)
	-- Make sure the player is still in the game so we don't cause memory leaks
	if player:IsDescendantOf(game) then
		self._groups[player] = groupName
		self.CmdrAdditions.Network:SendEvent(player, "UpdateGroup", groupName)
	end
end

function PermissionsServer:CanPlayerRunCommand(player, commandId)
	local groupName = self:GetPlayerGroup(player)
	return self.Controller:CanGroupRunCommand(groupName, commandId)
end

function PermissionsServer:SetRegistry(registry)
	self.Controller:SetRegistry(registry)
end

return PermissionsServer