local w=require(script.Parent.Parent.Constants)local O={}O.__index=O function O.get(w,...)local O=w.data if O==nil then return end for w,T in ipairs({...})do O=O[T]if O==nil then return end end return O end function O.getOr(w,...)local O={...}local T=table.remove(O,#O)local I=w:get(unpack(O))if I~=nil then return I elseif type(T)=="\102\117\110\099\116\105\111\110"then return T(unpack(O))else return T end end function O.getAnd(w,...)local O={...}local T=table.remove(O,#O)local I=w:get(unpack(O))if I~=nil then return T(I)end end function O.set(O,...)local T={...}local I=table.remove(T,#T)assert(I~=nil,"\077\117\115\116 \112\114\111\118\105\100\101 \097 \118\097\108\117\101 \116\111 \115\101\116")if I==w.None then I=nil end local q=O.components[w.SCOPE_BASE]or{}while#T>1 do q=q[table.remove(T,1)]end if T[1]then q[T[1]]=I else q=I end return O.rocs._aggregates:addComponent(O.instance,getmetatable(O),w.SCOPE_BASE,q)end function O.listen(T,w,O)if not T._listeners then T._listeners={}end if not T._listeners[w]then T._listeners[w]={}end table.insert(T._listeners[w],O)return O end function O.removeListener(T,w,O)if T._listeners and T._listeners[w]then for I,q in ipairs(T._listeners[w])do if q==O then table.remove(T._listeners[w],I)break end end if#T._listeners[w]==0 then T._listeners[w]=nil if next(T._listeners)==nil then T._listeners=nil end end end end function O.dispatch(O,w,...)if O[w]then O[w](O,...)end if O._listeners and O._listeners[w]then for w,O in ipairs(O._listeners[w])do O(...)end end end function O.__tostring(w)return("\065\103\103\114\101\103\097\116\101\040\037\115\041"):format(w.name)end return O
local Constants = require(script.Parent.Parent.Constants)

local Aggregate = {}
Aggregate.__index = Aggregate

function Aggregate:get(...)
	local object = self.data

	if object == nil then
		return
	end

	for _, field in ipairs({...}) do
		object = object[field]

		if object == nil then
			return
		end
	end

	return object
end

function Aggregate:getOr(...)
	local path = {...}
	local default = table.remove(path, #path)

	local value = self:get(unpack(path))

	if value ~= nil then
		return value
	elseif type(default) == "function" then
		return default(unpack(path))
	else
		return default
	end
end

function Aggregate:getAnd(...)
	local path = {...}
	local callback = table.remove(path, #path)

	local value = self:get(unpack(path))

	if value ~= nil then
		return callback(value)
	end
end

function Aggregate:set(...)
		local path = {...}
		local value = table.remove(path, #path)

		assert(value ~= nil, "Must provide a value to set")

		if value == Constants.None then
			value = nil
		end

		local currentValue = self.components[Constants.SCOPE_BASE] or {}

		while #path > 1 do
			currentValue = currentValue[table.remove(path, 1)]
		end

		if path[1] then
			currentValue[path[1]] = value
		else
			currentValue = value
		end

		return self.rocs._aggregates:addComponent(self.instance, getmetatable(self), Constants.SCOPE_BASE, currentValue)
end

function Aggregate:listen(eventName, callback)
	if not self._listeners then
		self._listeners = {}
	end

	if not self._listeners[eventName] then
		self._listeners[eventName] = {}
	end

	table.insert(self._listeners[eventName], callback)

	return callback
end

function Aggregate:removeListener(eventName, callback)
	if self._listeners and self._listeners[eventName] then
		for i, listener in ipairs(self._listeners[eventName]) do
			if listener == callback then
				table.remove(self._listeners[eventName], i)
				break
			end
		end

		if #self._listeners[eventName] == 0 then
			self._listeners[eventName] = nil

			if next(self._listeners) == nil then
				self._listeners = nil
			end
		end
	end
end

function Aggregate:dispatch(eventName, ...)
	if self[eventName] then
		self[eventName](self, ...)
	end

	if self._listeners and self._listeners[eventName] then
		for _, listener in ipairs(self._listeners[eventName]) do
			listener(...)
		end
	end
end

function Aggregate:__tostring()
	return ("Aggregate(%s)"):format(self.name)
end

return Aggregate
