local p=import("\046\047\116\121\112\101\075\101\121")local function g(p,...)local g={}local Q=#p for Q=1,Q,1 do g[Q]=p[Q]end for p=1,select("\035",...),1 do g[Q+p]=select(p,...)end return g end local function Q(p,g)local Q={}for c=1,#p,1 do if p[c]~=g then table.insert(Q,p[c])end end return Q end local c={}c.__index=c function c.new()local g={listeners={}}local Q=newproxy(true);(getmetatable(Q)).__index=c;(getmetatable(Q)).internal=g;(getmetatable(Q))[p]="\082\066\088\083\099\114\105\112\116\083\105\103\110\097\108"return Q end function c.Connect(c,p)local V=(getmetatable(c)).internal V.listeners=g(V.listeners,p)local w={}w.Connected=true function w.Disconnect()w.Connected=false V.listeners=Q(V.listeners,p)end return w end function c.Fire(p,...)local g=(getmetatable(p)).internal for p,g in ipairs(g.listeners)do local Q=coroutine.create(function(...)return g(...)end)coroutine.resume(Q,...)end end function c.Wait(p)error("\083\105\103\110\097\108\058\087\097\105\116 \105\115 \110\111\116 \105\109\112\108\101\109\101\110\116\101\100 \105\110 \076\101\109\117\114",2)end function c._DisconnectAllListeners(p)local g=(getmetatable(p)).internal g.listeners={}end return c
--[[
	A limited, simple implementation of a Signal.

	Handlers are fired in order, and (dis)connections are properly handled when
	executing an event.
]]

local typeKey = import("./typeKey")

local function immutableAppend(list, ...)
	local new = {}
	local len = #list

	for key = 1, len do
		new[key] = list[key]
	end

	for i = 1, select("#", ...) do
		new[len + i] = select(i, ...)
	end

	return new
end

local function immutableRemoveValue(list, removeValue)
	local new = {}

	for i = 1, #list do
		if list[i] ~= removeValue then
			table.insert(new, list[i])
		end
	end

	return new
end

local Signal = {}

Signal.__index = Signal

function Signal.new()
	local internal = {
		listeners = {},
	}

	local self = newproxy(true)
	getmetatable(self).__index = Signal
	getmetatable(self).internal = internal
	getmetatable(self)[typeKey] = "RBXScriptSignal"

	return self
end

function Signal:Connect(callback)
	local internal = getmetatable(self).internal

	internal.listeners = immutableAppend(internal.listeners, callback)

	local connection = {}
	connection.Connected = true

	function connection.Disconnect()
		connection.Connected = false
		internal.listeners = immutableRemoveValue(internal.listeners, callback)
	end

	return connection
end

function Signal:Fire(...)
	-- TODO: Move this function somewhere else, since it isn't part of the
	-- public API that Roblox exposes.

	local internal = getmetatable(self).internal

	for _, listener in ipairs(internal.listeners) do
		-- Busted uses tables for spies, which angers coroutine.create if we use
		-- them directly.
		local co = coroutine.create(function(...)
			return listener(...)
		end)

		-- TODO: Report errors in a nice way that won't spam tests
		coroutine.resume(co, ...)
	end
end

function Signal:Wait()
	-- Once Lemur has an event loop, this can be revisited.
	error("Signal:Wait is not implemented in Lemur", 2)
end

function Signal:_DisconnectAllListeners()
	local internal = getmetatable(self).internal

	internal.listeners = {}
end

return Signal