local Z={}Z.__index=Z function Z.new()local R=setmetatable({_bindable=Instance.new("\066\105\110\100\097\098\108\101\069\118\101\110\116");_connections={};_args={};_threads=0,_id=0},Z)return R end function Z.Is(R)return type(R)=="\116\097\098\108\101"and getmetatable(R)==Z end function Z.Fire(Z,...)local R=Z._id Z._id=Z._id+1 Z._args[R]={#Z._connections+Z._threads;{n=select("\035",...),...}}Z._threads=0 Z._bindable:Fire(R)end function Z.Wait(Z)Z._threads=Z._threads+1 local R=Z._bindable.Event:Wait()local c=Z._args[R]c[1]=c[1]-1 if c[1]<=0 then Z._args[R]=nil end return table.unpack(c[2],1,c[2].n)end function Z.WaitPromise(Z)return Promise.new(function(R)R(Z:Wait())end)end function Z.Connect(R,Z)local c=Connection.new(R,R._bindable.Event:Connect(function(c)local k=R._args[c]k[1]=k[1]-1 if k[1]<=0 then R._args[c]=nil end Z(table.unpack(k[2],1,k[2].n))end))table.insert(R._connections,c)return c end function Z.DisconnectAll(Z)for Z,R in ipairs(Z._connections)do if R._conn then R._conn:Disconnect()end end Z._connections={}Z._args={}end function Z.Destroy(Z)Z:DisconnectAll()Z._bindable:Destroy()end function Z.Init(Z)Promise=Z.Shared.Promise end return Z


local Signal = {}
Signal.__index = Signal


function Signal.new()
	local self = setmetatable({
		_bindable = Instance.new("BindableEvent");
		_connections = {};
		_args = {};
		_threads = 0;
		_id = 0;
	}, Signal)
	return self
end


function Signal.Is(obj)
	return (type(obj) == "table" and getmetatable(obj) == Signal)
end


function Signal:Fire(...)
	local id = self._id
	self._id = self._id + 1
	self._args[id] = {#self._connections + self._threads, {n = select("#", ...), ...}}
	self._threads = 0
	self._bindable:Fire(id)
end


function Signal:Wait()
	self._threads = self._threads + 1
	local id = self._bindable.Event:Wait()
	local args = self._args[id]
	args[1] = args[1] - 1
	if (args[1] <= 0) then
		self._args[id] = nil
	end
	return table.unpack(args[2], 1, args[2].n)
end


function Signal:WaitPromise()
	return Promise.new(function(resolve)
		resolve(self:Wait())
	end)
end


function Signal:Connect(handler)
	local connection = Connection.new(self, self._bindable.Event:Connect(function(id)
		local args = self._args[id]
		args[1] = args[1] - 1
		if (args[1] <= 0) then
			self._args[id] = nil
		end
		handler(table.unpack(args[2], 1, args[2].n))
	end))
	table.insert(self._connections, connection)
	return connection
end


function Signal:DisconnectAll()
	for _,c in ipairs(self._connections) do
		if (c._conn) then
			c._conn:Disconnect()
		end
	end
	self._connections = {}
	self._args = {}
end


function Signal:Destroy()
	self:DisconnectAll()
	self._bindable:Destroy()
end


function Signal:Init()
	Promise = self.Shared.Promise
end


return Signal
