local f={}f.__index=f function f.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},f)return R end function f.Is(R)return type(R)=="\116\097\098\108\101"and getmetatable(R)==f end function f.Fire(f,...)local R=f._id f._id=f._id+1 f._args[R]={#f._connections+f._threads,{n=select("\035",...);...}}f._threads=0 f._bindable:Fire(R)end function f.Wait(f)f._threads=f._threads+1 local R=f._bindable.Event:Wait()local s=f._args[R]s[1]=s[1]-1 if s[1]<=0 then f._args[R]=nil end return table.unpack(s[2],1,s[2].n)end function f.WaitPromise(f)return Promise.new(function(R)R(f:Wait())end)end function f.Connect(R,f)local s=Connection.new(R,R._bindable.Event:Connect(function(s)local Z=R._args[s]Z[1]=Z[1]-1 if Z[1]<=0 then R._args[s]=nil end f(table.unpack(Z[2],1,Z[2].n))end))table.insert(R._connections,s)return s end function f.DisconnectAll(f)for f,R in ipairs(f._connections)do if R._conn then R._conn:Disconnect()end end f._connections={}f._args={}end function f.Destroy(f)f:DisconnectAll()f._bindable:Destroy()end function f.Init(f)Promise=f.Shared.Promise end return f
--------------------------------------------

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
