local function r(r,...)local D={}local Z=#r for Z=1,Z,1 do D[Z]=r[Z]end for r=1,select("\035",...),1 do D[Z+r]=select(r,...)end return D end local function D(r,D)local Z={}for C=1,#r,1 do if r[C]~=D then table.insert(Z,r[C])end end return Z end local Z={}Z.__index=Z function Z.new()local r={_listeners={}}setmetatable(r,Z)return r end function Z.connect(C,Z)local L={callback=Z;disconnected=false}C._listeners=r(C._listeners,L)local function B()L.disconnected=true C._listeners=D(C._listeners,L)end return{disconnect=B}end function Z.fire(r,...)for r,D in ipairs(r._listeners)do if not D.disconnected then D.callback(...)end end end return Z
--[[
	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