local I={}I.ClassName="\077\097\105\100"function I.new()return setmetatable({_tasks={}},I)end function I.isMaid(I)return type(I)=="\116\097\098\108\101"and I.ClassName=="\077\097\105\100"end function I.__index(T,J)if I[J]then return I[J]else return T._tasks[J]end end function I.__newindex(d,J,T)if I[J]~=nil then error(("\'\037\115\' \105\115 \114\101\115\101\114\118\101\100"):format(tostring(J)),2)end local q=d._tasks local t=q[J]if t==T then return end q[J]=T if t then if type(t)=="\102\117\110\099\116\105\111\110"then t()elseif typeof(t)=="\082\066\088\083\099\114\105\112\116\067\111\110\110\101\099\116\105\111\110"then t:Disconnect()elseif t.Destroy then t:Destroy()elseif t.destroy then t:destroy()end end end function I.giveTask(J,I)if not I then error("\084\097\115\107 \099\097\110\110\111\116 \098\101 \102\097\108\115\101 \111\114 \110\105\108",2)end local T=#J._tasks+1 J[T]=I if type(I)=="\116\097\098\108\101"and not(I.Destroy or I.destroy)then warn("\091\077\097\105\100\046\071\105\118\101\084\097\115\107\093 - \071\097\118\101 \116\097\098\108\101 \116\097\115\107 \119\105\116\104\111\117\116 \046\068\101\115\116\114\111\121\n\n"..debug.traceback())end return T end function I.give(J,I)local T if type(I)=="\116\097\098\108\101"and I.isAPromise then _,T=J:givePromise(I)else T=J:giveTask(I)end return I,T end function I.doCleaning(I)local J=I._tasks for I,T in pairs(J)do if typeof(T)=="\082\066\088\083\099\114\105\112\116\067\111\110\110\101\099\116\105\111\110"then J[I]=nil T:Disconnect()end end local T,d=next(J)while d~=nil do J[T]=nil if type(d)=="\102\117\110\099\116\105\111\110"then d()elseif typeof(d)=="\082\066\088\083\099\114\105\112\116\067\111\110\110\101\099\116\105\111\110"then d:Disconnect()elseif d.Destroy then d:Destroy()elseif d.destroy then d:destroy()end T,d=next(J)end end I.destroy=I.doCleaning I.clean=I.doCleaning return I
-- Maid
-- Author: Quenty
-- Source: https://github.com/Quenty/NevermoreEngine/blob/8ef4242a880c645b2f82a706e8074e74f23aab06/Modules/Shared/Events/Maid.lua
-- License: MIT (https://github.com/Quenty/NevermoreEngine/blob/version2/LICENSE.md)


---	Manages the cleaning of events and other things.
-- Useful for encapsulating state and make deconstructors easy
-- @classmod Maid
-- @see Signal

local Maid = {}
Maid.ClassName = "Maid"

--- Returns a new Maid object
-- @constructor Maid.new()
-- @treturn Maid
function Maid.new()
	return setmetatable({
		_tasks = {}
	}, Maid)
end

function Maid.isMaid(value)
	return type(value) == "table" and value.ClassName == "Maid"
end

--- Returns Maid[key] if not part of Maid metatable
-- @return Maid[key] value
function Maid:__index(index)
	if Maid[index] then
		return Maid[index]
	else
		return self._tasks[index]
	end
end

--- Add a task to clean up. Tasks given to a maid will be cleaned when
--  maid[index] is set to a different value.
-- @usage
-- Maid[key] = (function)         Adds a task to perform
-- Maid[key] = (event connection) Manages an event connection
-- Maid[key] = (Maid)             Maids can act as an event connection, allowing a Maid to have other maids to clean up.
-- Maid[key] = (Object)           Maids can cleanup objects with a `Destroy` method
-- Maid[key] = nil                Removes a named task. If the task is an event, it is disconnected. If it is an object,
--                                it is destroyed.
function Maid:__newindex(index, newTask)
	if Maid[index] ~= nil then
		error(("'%s' is reserved"):format(tostring(index)), 2)
	end

	local tasks = self._tasks
	local oldTask = tasks[index]

	if oldTask == newTask then
		return
	end

	tasks[index] = newTask

	if oldTask then
		if type(oldTask) == "function" then
			oldTask()
		elseif typeof(oldTask) == "RBXScriptConnection" then
			oldTask:Disconnect()
		elseif oldTask.Destroy then
			oldTask:Destroy()
		elseif oldTask.destroy then
			oldTask:destroy()
		end
	end
end

--- Same as indexing, but uses an incremented number as a key.
-- @param task An item to clean
-- @treturn number taskId
function Maid:giveTask(task)
	if not task then
		error("Task cannot be false or nil", 2)
	end

	local taskId = #self._tasks+1
	self[taskId] = task

	if type(task) == "table" and (not (task.Destroy or task.destroy)) then
		warn("[Maid.GiveTask] - Gave table task without .Destroy\n\n" .. debug.traceback())
	end

	return taskId
end

--[[ I wont' be using promises for TopbarPlus so we can ignore this method
function Maid:givePromise(promise)
	if (promise:getStatus() ~= Promise.Status.Started) then
		return promise
	end

	local newPromise = Promise.resolve(promise)
	local id = self:giveTask(newPromise)

	-- Ensure GC
	newPromise:finally(function()
		self[id] = nil
	end)

	return newPromise, id
end--]]

function Maid:give(taskOrPromise)
	local taskId
	if type(taskOrPromise) == "table" and taskOrPromise.isAPromise then
		_, taskId = self:givePromise(taskOrPromise)
	else
		taskId = self:giveTask(taskOrPromise)
	end
	return taskOrPromise, taskId
end

--- Cleans up all tasks.
-- @alias Destroy
function Maid:doCleaning()
	local tasks = self._tasks

	-- Disconnect all events first as we know this is safe
	for index, task in pairs(tasks) do
		if typeof(task) == "RBXScriptConnection" then
			tasks[index] = nil
			task:Disconnect()
		end
	end

	-- Clear out tasks table completely, even if clean up tasks add more tasks to the maid
	local index, task = next(tasks)
	while task ~= nil do
		tasks[index] = nil
		if type(task) == "function" then
			task()
		elseif typeof(task) == "RBXScriptConnection" then
			task:Disconnect()
		elseif task.Destroy then
			task:Destroy()
		elseif task.destroy then
			task:destroy()
		end
		index, task = next(tasks)
	end
end

--- Alias for DoCleaning()
-- @function Destroy
Maid.destroy = Maid.doCleaning
Maid.clean = Maid.doCleaning

return Maid