local W=import("\046\047\116\121\112\101\075\101\121")local function m(W,...)local m={}local j=#W for j=1,j,1 do m[j]=W[j]end for W=1,select("\035",...),1 do m[j+W]=select(W,...)end return m end local function j(W,m)local j={}for V=1,#W,1 do if W[V]~=m then table.insert(j,W[V])end end return j end local V={}V.__index=V function V.new()local m={listeners={}}local j=newproxy(true);(getmetatable(j)).__index=V;(getmetatable(j)).internal=m;(getmetatable(j))[W]="\082\066\088\083\099\114\105\112\116\083\105\103\110\097\108"return j end function V.Connect(V,W)local n=(getmetatable(V)).internal n.listeners=m(n.listeners,W)local R={}R.Connected=true function R.Disconnect()R.Connected=false n.listeners=j(n.listeners,W)end return R end function V.Fire(W,...)local m=(getmetatable(W)).internal for W,m in ipairs(m.listeners)do local j=coroutine.create(function(...)return m(...)end)coroutine.resume(j,...)end end function V.Wait(W)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 V._DisconnectAllListeners(W)local m=(getmetatable(W)).internal m.listeners={}end return V
--[[
	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