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._selectors={}for w,T in pairs(...)do if type(T)=="\102\117\110\099\116\105\111\110"then error("\067\097\110\110\111\116 \104\097\118\101 \102\117\110\099\116\105\111\110\115 \105\110 \115\101\108\101\099\116\111\114\115\046\097\110\121",2)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 T=O.instance if not w._lookup[T]then w._lookup[T]=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]and not w:check(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 T=O.instance if w._lookup[T]then w:_trigger("\111\110\085\112\100\097\116\101\100",O)else w._lookup[T]=true w:_trigger("\111\110\065\100\100\101\100",O)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)do for w,T in pairs(T:fetch())do O[T]=true end end for w in pairs(O)do table.insert(O,w)O[w]=nil end end return O end function T.check(O,w)for O,T in pairs(O._selectors)do if T:check(w)then return true end end return false end return T
local BaseSelector = require(script.Parent.BaseSelector)
local Util = require(script.Parent.Util)

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

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

	self._selectors = {}
	for _, property in pairs(...) do
		if type(property) == "function" then
			error("Cannot have functions in selectors.any", 2)
		else
			table.insert(self._selectors, Util.resolve(rocs, property))
		end
	end

	return self
end

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

		selector:onRemoved(
			function(aggregate)
				local instance = aggregate.instance
				if self._lookup[instance] and not self:check(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
					self:_trigger("onUpdated", aggregate)
				else
					self._lookup[instance] = true
					self:_trigger("onAdded", aggregate)
				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 AnySelector:instances()
	local instances = {}

	if #self._selectors > 0 then
		-- accumulate entities into cache, only-once
		for _, selector in pairs(self._selectors) do
			for _, instance in pairs(selector:fetch()) do
				instances[instance] = true
			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 AnySelector:check(instance)
	for _, selector in pairs(self._selectors) do
		if selector:check(instance) then
			return true
		end
	end

	return false
end

return AnySelector
