local w=require(script.Parent.BaseSelector)local O=setmetatable({},w)O.__index=O function O.new(T,I,q,B)assert(I)local f=setmetatable(w.new(T),O)f._componentResolvable=I f._properties=q or{}f._metaComponents=B or{}f._rocsHooks={}return f end function O._listen(w)w._rocsHooks.onAdded=w._rocs:registerComponentHook(w._componentResolvable,"\111\110\065\100\100\101\100",function(O)local T=O.instance if not w._lookup[T]and w:check(T)then w._lookup[T]=true w:_trigger("\111\110\065\100\100\101\100",O)end end)w._rocsHooks.onRemoved=w._rocs:registerComponentHook(w._componentResolvable,"\111\110\082\101\109\111\118\101\100",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)w._rocsHooks.onUpdated=w._rocs:registerComponentHook(w._componentResolvable,"\111\110\085\112\100\097\116\101\100",function(O)local T=O.instance if w._lookup[T]then if w:check(T)then w:_trigger("\111\110\085\112\100\097\116\101\100",O)else w._lookup[T]=nil w:_trigger("\111\110\082\101\109\111\118\101\100",O)end else if w:check(T)then w._lookup[T]=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)w._rocsHooks.onParentUpdated=w._rocs:registerComponentHook(w._componentResolvable,"\111\110\080\097\114\101\110\116\085\112\100\097\116\101\100",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 function w.destroy(w)if not w._ready then return end w._ready=nil for O,T in pairs(w._hooks)do w._hooks[O]={}end for O,T in pairs(w._rocsHooks)do w._rocs:unregisterComponentHook(w._componentResolvable,O,T)end w._lookup={}return w end function O.instances(w)local O={}for w,T in pairs(w._rocs:getComponents(w._componentResolvable))do O[T.instance]=true end for w in pairs(O)do table.insert(O,w)O[w]=nil end return O end function O.check(O,w)local T=(O._rocs:getEntity(w)):getComponent(O._componentResolvable)if not T then return false end for w,O in pairs(O._properties)do end for w,O in pairs(O._metaComponents)do end return true end return O
local BaseSelector = require(script.Parent.BaseSelector)

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

function ComponentSelector.new(rocs, componentResolvable, properties, metaComponents)
	assert(componentResolvable)
	local self = setmetatable(BaseSelector.new(rocs), ComponentSelector)

	self._componentResolvable = componentResolvable
	self._properties = properties or {}
	self._metaComponents = metaComponents or {}

	self._rocsHooks = {}

	return self
end

function ComponentSelector:_listen()

	self._rocsHooks.onAdded = self._rocs:registerComponentHook(
		self._componentResolvable,
		"onAdded",
		function(aggregate)
			local instance = aggregate.instance
			if not self._lookup[instance] and self:check(instance) then
				self._lookup[instance] = true
				self:_trigger("onAdded", aggregate)
			end
		end
	)

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

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

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

end

function BaseSelector:destroy() -- override
	if not self._ready then
		return
	end
	self._ready = nil

	for category, _ in pairs(self._hooks) do
		self._hooks[category] = {}
	end

	for lifecycle, hook in pairs(self._rocsHooks) do
		self._rocs:unregisterComponentHook(self._componentResolvable, lifecycle, hook)
	end

	self._lookup = {}

	return self
end

function ComponentSelector:instances()
	local instances = {}

	for _, component in pairs(self._rocs:getComponents(self._componentResolvable)) do
		instances[component.instance] = true
	end

	for instance in pairs(instances) do
		table.insert(instances, instance)
		instances[instance] = nil
	end

	return instances
end

function ComponentSelector:check(instance)
	local component = self._rocs:getEntity(instance):getComponent(self._componentResolvable)
	if not component then
		return false
	end

	for key, property in pairs(self._properties) do
		-- TODO handle properties
	end

	for name, _ in pairs(self._metaComponents) do
		-- TODO handle meta-components
	end

	return true
end

return ComponentSelector
