--[[
	Updates all Spring objects.
]]

local function updateAllSprings(timeStep: number)
	for damping, dampingBucket in pairs(springBuckets) do
		for speed, speedBucket in pairs(dampingBucket) do
			local posPosCoef, posVelCoef, velPosCoef, velVelCoef = springCoefficients(timeStep, damping, speed)

			for spring in pairs(speedBucket) do
				local goals = spring._springGoals
				local positions = spring._springPositions
				local velocities = spring._springVelocities

				local isMoving = false

				for index, goal in ipairs(goals) do
					local oldPosition = positions[index]
					local oldVelocity = velocities[index]

					local oldDisplacement = oldPosition - goal

					local newDisplacement = oldDisplacement * posPosCoef + oldVelocity * posVelCoef
					local newVelocity = oldDisplacement * velPosCoef + oldVelocity * velVelCoef

					if
						math.abs(newDisplacement) > MOVEMENT_EPSILON or
						math.abs(newVelocity) > MOVEMENT_EPSILON
					then
						isMoving = true
					end

					positions[index] = newDisplacement + goal
					velocities[index] = newVelocity
				end

				-- if the spring moved a significant distance, update its
				-- current value, otherwise stop animating
				if isMoving then
					spring._currentValue = packType(positions, spring._currentType)
					updateAll(spring)
				else
					SpringScheduler.remove(spring)
				end
			end
		end
	end
end

RunService:BindToRenderStep(
	"__FusionSpringScheduler",
	Enum.RenderPriority.First.Value,
	updateAllSprings
)

return SpringScheduler
