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