local function W(W,...)local S={}local v=#W for v=1,v,1 do S[v]=W[v]end for W=1,select("\035",...),1 do S[v+W]=select(W,...)end return S end local function S(W,S)local v={}for G=1,#W,1 do if W[G]~=S then table.insert(v,W[G])end end return v end local v={}v.__index=v function v.new()local W={_listeners={}}setmetatable(W,v)return W end function v.connect(G,v)local A={callback=v;disconnected=false}G._listeners=W(G._listeners,A)local function R()A.disconnected=true G._listeners=S(G._listeners,A)end return{disconnect=R}end function v.fire(W,...)for W,S in ipairs(W._listeners)do if not S.disconnected then S.callback(...)end end 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 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 self = {
		_listeners = {},
	}

	setmetatable(self, Signal)

	return self
end

function Signal:connect(callback)
	local listener = {
		callback = callback,
		disconnected = false,
	}

	self._listeners = immutableAppend(self._listeners, listener)

	local function disconnect()
		listener.disconnected = true
		self._listeners = immutableRemoveValue(self._listeners, listener)
	end

	return {
		disconnect = disconnect,
	}
end

function Signal:fire(...)
	for _, listener in ipairs(self._listeners) do
		if not listener.disconnected then
			listener.callback(...)
		end
	end
end

return Signal
