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