Option Strict On
Option Explicit On

Imports System
Imports Nexamas.UI.Motion

Namespace Nexamas.UI.Controls

    Partial Public NotInheritable Class MASProgressBar
#Region "Motion"

        Private Function ResolveRenderValue() As Double
            If _hasVisualValueOverride Then
                Return MASProgressBarValuePolicy.NormalizeValue(_visualValue, _minimum, _maximum)
            End If

            Return _value
        End Function

        Private Sub StartValueMotion(fromValue As Double,
                                     toValue As Double)
            fromValue = MASProgressBarValuePolicy.NormalizeValue(fromValue, _minimum, _maximum)
            toValue = MASProgressBarValuePolicy.NormalizeValue(toValue, _minimum, _maximum)

            If NearlyEqual(fromValue, toValue) Then
                StopValueMotion(syncToSemanticValue:=True)
                Return
            End If

            StopValueMotion(syncToSemanticValue:=False)

            _visualValue = fromValue
            _hasVisualValueOverride = True

            Dim fullDistance As Single = CSng(Math.Max(0.0001R, Math.Abs(_maximum - _minimum)))
            Dim plan As MASMotionTransitionPlan = MASMotionSystem.CreateDistanceScaledTransitionPlan(
                MASMotionTokenId.ValueChange,
                CSng(fromValue),
                CSng(toValue),
                fullDistance)

            _valueMotionRunner = MASMotionSystem.CreateTimelineRunner(
                owner:=Me,
                consumerName:="MASProgressBar.ValueChange",
                plan:=plan,
                requestFrame:=AddressOf InvalidateVisual,
                applyFrame:=AddressOf ApplyValueMotionFrame,
                completed:=AddressOf CompleteValueMotionFrame)
            _valueMotionRunner.Start()

            InvalidateVisual()
        End Sub

        Private Sub ApplyValueMotionFrame(frame As MASMotionFrame)
            If frame Is Nothing Then Return
            _visualValue = MASProgressBarValuePolicy.NormalizeValue(CDbl(frame.Value), _minimum, _maximum)
            _hasVisualValueOverride = True
            InvalidateVisual()
        End Sub

        Private Sub CompleteValueMotionFrame(frame As MASMotionFrame)
            StopValueMotion(syncToSemanticValue:=True)
            InvalidateVisual()
        End Sub

        Private Sub StopValueMotion(syncToSemanticValue As Boolean)
            If _valueMotionRunner IsNot Nothing Then
                _valueMotionRunner.Dispose()
                _valueMotionRunner = Nothing
            End If

            If syncToSemanticValue Then
                _visualValue = _value
                _hasVisualValueOverride = False
            End If
        End Sub

#End Region
    End Class

End Namespace
