local function g(g,...)local j={}local D=#g for D=1,D,1 do j[D]=g[D]end for g=1,select("\035",...),1 do j[D+g]=select(g,...)end return j end local function j(g,j)local D={}for v=1,#g,1 do if g[v]~=j then table.insert(D,g[v])end end return D end local D={}D.__index=D function D.new()local g={_listeners={}}setmetatable(g,D)return g end function D.connect(v,D)local F={callback=D;disconnected=false}v._listeners=g(v._listeners,F)local function G()F.disconnected=true v._listeners=j(v._listeners,F)end return{disconnect=G}end function D.fire(g,...)for g,j in ipairs(g._listeners)do if not j.disconnected then j.callback(...)end end end return D


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
