local g={}g.__index=g function g.Connect(Q,g,r,J)local O={_listener=g;_script_signal=Q,_disconnect_listener=r,_disconnect_param=J,_next=Q._head;_is_connected=true}setmetatable(O,ScriptConnection)Q._head=O Q._listener_count+=1 return O end function g.GetListenerCount(g)return g._listener_count end function g.Fire(g,...)local r=g._head while r~=nil do if r._is_connected==true then if not FreeRunnerThread then FreeRunnerThread=coroutine.create(RunEventHandlerInFreeThread)end task.spawn(FreeRunnerThread,r._listener,...)end r=r._next end end function g.FireUntil(r,g,...)local J=r._head while J~=nil do if J._is_connected==true then J._listener(...)if g()~=true then return end end J=J._next end end function MadworkScriptSignal.NewScriptSignal()return{_head=nil,_listener_count=0,Connect=g.Connect;GetListenerCount=g.GetListenerCount,Fire=g.Fire;FireUntil=g.FireUntil}end return MadworkScriptSignal


local ScriptSignal = {
	--[[
		_head = nil,
		_listener_count = 0,
	--]]
}
ScriptSignal.__index = ScriptSignal

function ScriptSignal:Connect(listener, disconnect_listener, disconnect_param) --> [ScriptConnection]

	local script_connection = {
		_listener = listener,
		_script_signal = self,
		_disconnect_listener = disconnect_listener,
		_disconnect_param = disconnect_param,

		_next = self._head,
		_is_connected = true,
	}
	setmetatable(script_connection, ScriptConnection)

	self._head = script_connection
	self._listener_count += 1

	return script_connection

end

function ScriptSignal:GetListenerCount() --> [number]
	return self._listener_count
end

function ScriptSignal:Fire(...)
	local item = self._head
	while item ~= nil do
		if item._is_connected == true then
			if not FreeRunnerThread then
				FreeRunnerThread = coroutine.create(RunEventHandlerInFreeThread)
			end
			task.spawn(FreeRunnerThread, item._listener, ...)
		end
		item = item._next
	end
end

function ScriptSignal:FireUntil(continue_callback, ...)
	local item = self._head
	while item ~= nil do
		if item._is_connected == true then
			item._listener(...)
			if continue_callback() ~= true then
				return
			end
		end
		item = item._next
	end
end

function MadworkScriptSignal.NewScriptSignal() --> [ScriptSignal]
	return {
		_head = nil,
		_listener_count = 0,
		Connect = ScriptSignal.Connect,
		GetListenerCount = ScriptSignal.GetListenerCount,
		Fire = ScriptSignal.Fire,
		FireUntil = ScriptSignal.FireUntil,
	}
end

return MadworkScriptSignal
