--[[
	Subscribe to a binding's change signal. This is only accessible by Roact.
]]

function Binding.subscribe(binding, handler)
	local internalData = binding[InternalData]

	--[[
		If this binding is mapped to another and does not have any subscribers,
		we need to create a subscription to our source binding so that updates
		get passed along to us
	]]
	if internalData.upstreamBinding ~= nil and internalData.subscriberCount == 0 then
		internalData.upstreamDisconnect = Binding.subscribe(internalData.upstreamBinding, function(value)
			Binding.update(binding, value)
		end)
	end

	local disconnect = internalData.changeSignal:subscribe(handler)
	internalData.subscriberCount = internalData.subscriberCount + 1

	local disconnected = false

	--[[
		We wrap the disconnect function so that we can manage our subscriptions
		when the disconnect is triggered
	]]
	return function()
		if disconnected then
			return
		end

		disconnected = true
		disconnect()
		internalData.subscriberCount = internalData.subscriberCount - 1

		--[[
			If our subscribers count drops to 0, we can safely unsubscribe from
			our source binding
		]]
		if internalData.subscriberCount == 0 and internalData.upstreamDisconnect ~= nil then
			internalData.upstreamDisconnect()
			internalData.upstreamDisconnect = nil
		end
	end
end
