-- Connection class

local Connection = {}
Connection.__index = Connection

export type SignalConnection = typeof(setmetatable(
	{} :: {
		_connected: boolean,
		_signal: ClassType,
		_fn: Callback,
		_next: SignalConnection?,
	},
	Connection
))

function Connection.new(signal: ClassType, fn: Callback): SignalConnection
	local self = {
		_connected = true,
		_signal = signal,
		_fn = fn,
		_next = nil,
	}

	setmetatable(self, Connection)

	return self
end

function Connection.Disconnect(self: SignalConnection)
	assert(self._connected, "Can't disconnect a connection twice.")
	self._connected = false

	-- Unhook the node, but DON'T clear it. That way any fire calls that are
	-- currently sitting on this node will be able to iterate forwards off of
	-- it, but any subsequent fire calls will not hit it, and it will be GCed
	-- when no more fire calls are sitting on it.
	if self._signal._handlerListHead and (self._signal._handlerListHead :: SignalConnection) == self then
		self._signal._handlerListHead = self._next
	else
		local prev = self._signal._handlerListHead
		while prev and prev._next ~= self do
			prev = prev._next
		end
		if prev then
			prev._next = self._next
		end
	end
end
