local w=require(script.Parent.BaseSelector)local O=require(script.Parent.Util)local T=setmetatable({},w)T.__index=T function T.new(I,...)local q=setmetatable(w.new(I),T)q._checks={}for w,T in pairs(...)do if type(T)=="\102\117\110\099\116\105\111\110"then table.insert(q._checks,T)else table.insert(q._selectors,O.resolve(I,T))end end return q end function T._listen(w)for O,T in pairs(w._selectors)do T:onAdded(function(O)local I=O.instance if not w._lookup[I]and w:check(I,T)then w._lookup[I]=true w:_trigger("\111\110\065\100\100\101\100",O)end end)T:onRemoved(function(O)local T=O.instance if w._lookup[T]then w._lookup[T]=nil w:_trigger("\111\110\082\101\109\111\118\101\100",O)end end)T:onUpdated(function(O)local I=O.instance if w._lookup[I]then if w:check(I,T)then w:_trigger("\111\110\085\112\100\097\116\101\100",O)else w._lookup[I]=nil w:_trigger("\111\110\082\101\109\111\118\101\100",O)end else if w:check(I,T)then w._lookup[I]=true w:_trigger("\111\110\065\100\100\101\100",O)else w:_trigger("\111\110\085\112\100\097\116\101\100",O)end end end)T:onParentUpdated(function(O)if w._lookup[O.instance]then w:_trigger("\111\110\080\097\114\101\110\116\085\112\100\097\116\101\100",O)end end)end end function T.instances(w)local O={}if#w._selectors>0 then for w,T in pairs(w._selectors[1]:fetch())do O[T]=true end for w,T in pairs(w._checks)do for w in pairs(O)do if not T(w)then O[w]=nil end end end for T=2,#w._selectors,1 do local I=w._selectors[T]for w in pairs(O)do if not I:check(w)then O[w]=nil end end end for w in pairs(O)do table.insert(O,w)O[w]=nil end end return O end function T.check(T,w,O)for O,T in pairs(T._checks)do if not T(w)then return false end end for T,I in pairs(T._selectors)do if O~=I and not I:check(w)then return false end end return true end return T
local BaseSelector = require(script.Parent.BaseSelector)
local Util = require(script.Parent.Util)

local AllSelector = setmetatable({}, BaseSelector)
AllSelector.__index = AllSelector

function AllSelector.new(rocs, ...)
	local self = setmetatable(BaseSelector.new(rocs), AllSelector)

	self._checks = {}
	for _, property in pairs(...) do
		if type(property) == "function" then
			table.insert(self._checks, property)
		else
			table.insert(self._selectors, Util.resolve(rocs, property))
		end
	end

	return self
end

function AllSelector:_listen()
	for _, selector in pairs(self._selectors) do
		selector:onAdded(
			function(aggregate)
				local instance = aggregate.instance
				if not self._lookup[instance] and self:check(instance, selector) then
					self._lookup[instance] = true
					self:_trigger("onAdded", aggregate)
				end
			end
		)

		selector:onRemoved(
			function(aggregate)
				local instance = aggregate.instance
				if self._lookup[instance] then
					self._lookup[instance] = nil
					self:_trigger("onRemoved", aggregate)
				end
			end
		)

		selector:onUpdated(
			function(aggregate)
				local instance = aggregate.instance
				if self._lookup[instance] then
					if self:check(instance, selector) then
						self:_trigger("onUpdated", aggregate)
					else
						self._lookup[instance] = nil
						self:_trigger("onRemoved", aggregate)
					end
				else
					if self:check(instance, selector) then
						self._lookup[instance] = true
						self:_trigger("onAdded", aggregate)
					else
						self:_trigger("onUpdated", aggregate)
					end
				end
			end
		)

		-- TODO: is this right?
		selector:onParentUpdated(
			function(aggregate)
				if self._lookup[aggregate.instance] then
					self:_trigger("onParentUpdated", aggregate)
				end
			end
		)
	end
end

function AllSelector:instances()
	local instances = {}

	if #self._selectors > 0 then
		-- get first selection of entities
		for _, instance in pairs(self._selectors[1]:fetch()) do
			instances[instance] = true
		end

		-- filter the ones out that don't match function checks
		for _, check in pairs(self._checks) do
			for instance in pairs(instances) do
				if not check(instance) then
					instances[instance] = nil
				end
			end
		end

		-- filter the ones out that don't match other selectors
		for i = 2, #self._selectors do
			local selector = self._selectors[i]
			for instance in pairs(instances) do
				if not selector:check(instance) then
					instances[instance] = nil
				end
			end
		end

		-- turn lookup into array
		for instance in pairs(instances) do
			table.insert(instances, instance)
			instances[instance] = nil
		end
	end

	return instances
end

function AllSelector:check(instance, exceptSelector)
	for _, check in pairs(self._checks) do
		if not check(instance) then
			return false
		end
	end

	for _, selector in pairs(self._selectors) do
		if exceptSelector ~= selector and not selector:check(instance) then
			return false
		end
	end

	return true
end

return AllSelector
