local E={}E.__index=E function E.new(Y)local O=setmetatable({Config=Y,Groups={}},E)for E,Y in pairs(Y.Groups)do O.Groups[Y.Name]={Name=Y.Name;Index=E;AllowHigherGroups=true}end return O end function E.SetRegistry(Y,E)Y.Registry=E end function E.GetDefaultGroup(E)return E.Config.Groups[#E.Config.Groups].Name end function E.GetCommandGroup(Y,E)assert(E,"\109\105\115\115\105\110\103 \097\114\103\117\109\101\110\116 \035\049\058 \099\111\109\109\097\110\100\073\100")return Y.Config.CommandGroups[E]or Y.Config.DefaultCommandGroup end function E.CanGroupAccessOtherGroup(O,E,Y)assert(E,"\109\105\115\115\105\110\103 \097\114\103\117\109\101\110\116 \035\049\058 \103\114\111\117\112\078\097\109\101")assert(Y,"\109\105\115\115\105\110\103 \097\114\103\117\109\101\110\116 \035\050\058 \116\097\114\103\101\116\071\114\111\117\112\078\097\109\101")local x=O.Groups[E]local L=O.Groups[Y]if x.Name==L.Name then return true end if L.AllowHigherGroups and x.Index<L.Index then return true end return false end function E.CanGroupRunCommand(O,E,Y)assert(E,"\109\105\115\115\105\110\103 \097\114\103\117\109\101\110\116 \035\049\058 \103\114\111\117\112\078\097\109\101")assert(Y,"\109\105\115\115\105\110\103 \097\114\103\117\109\101\110\116 \035\050\058 \099\111\109\109\097\110\100\073\100")local x=O.Registry.Commands[Y]if x.Group=="\067\109\100\114\065\100\100\105\116\105\111\110\115"or O.Config.BlockForeignCommands then local Y=O:GetCommandGroup(x.Name)return O:CanGroupAccessOtherGroup(E,Y)else return true end end return E
local GroupController = {}
GroupController.__index = GroupController

function GroupController.new(config)
	local self = setmetatable({
		Config = config,
		Groups = {}
	}, GroupController)

	for index, group in pairs(config.Groups) do
		self.Groups[group.Name] = {
			Name = group.Name,
			Index = index,
			AllowHigherGroups = true
		}
	end

	return self
end

function GroupController:SetRegistry(registry)
	self.Registry = registry
end

function GroupController:GetDefaultGroup()
	return self.Config.Groups[#self.Config.Groups].Name
end

function GroupController:GetCommandGroup(commandId)
	assert(commandId, "missing argument #1: commandId")
	return self.Config.CommandGroups[commandId] or self.Config.DefaultCommandGroup
end

function GroupController:CanGroupAccessOtherGroup(groupName, targetGroupName)
	assert(groupName, "missing argument #1: groupName")
	assert(targetGroupName, "missing argument #2: targetGroupName")

	local group = self.Groups[groupName]
	local targetGroup = self.Groups[targetGroupName]

	if group.Name == targetGroup.Name then
		return true
	end

	if targetGroup.AllowHigherGroups and group.Index < targetGroup.Index then
		return true
	end

	return false
end

function GroupController:CanGroupRunCommand(groupName, commandId)
	assert(groupName, "missing argument #1: groupName")
	assert(commandId, "missing argument #2: commandId")

	local command = self.Registry.Commands[commandId]

	if command.Group == "CmdrAdditions" or self.Config.BlockForeignCommands then
		local requiredGroup = self:GetCommandGroup(command.Name)
		return self:CanGroupAccessOtherGroup(groupName, requiredGroup)
	else
		return true
	end
end

return GroupController