Option Strict On
Option Explicit On

Imports System
Imports Nexamas.UI.Motion
Imports SkiaSharp

Namespace Nexamas.UI.Controls

    Partial Public NotInheritable Class MASExpander

#Region "Disclosure motion"

        Private _disclosureMotionRunner As MASMotionTimelineRunner
        Private _disclosureProgress As Single = 1.0F
        Private _hasDisclosureMotion As Boolean

        Private Sub StartDisclosureMotion(previousExpanded As Boolean,
                                          nextExpanded As Boolean)
            If _disposedLocal Then Return
            If previousExpanded = nextExpanded Then Return

            StopDisclosureMotion(resetToCurrentState:=False)

            Dim fromProgress As Single = If(previousExpanded, 1.0F, 0.0F)
            Dim toProgress As Single = If(nextExpanded, 1.0F, 0.0F)
            _disclosureProgress = fromProgress
            _hasDisclosureMotion = True

            Dim token As MASMotionTokenId = If(nextExpanded, MASMotionTokenId.DisclosureOpen, MASMotionTokenId.DisclosureClose)
            Dim plan As MASMotionTransitionPlan = MASMotionSystem.CreateTransitionPlan(token, fromProgress, toProgress)
            If Not plan.ShouldAnimate Then
                CompleteDisclosureMotionFrame(Nothing)
                Return
            End If

            _disclosureMotionRunner = MASMotionSystem.CreateTimelineRunner(
                owner:=Me,
                consumerName:="MASExpander.Disclosure",
                plan:=plan,
                requestFrame:=AddressOf InvalidateVisual,
                applyFrame:=AddressOf ApplyDisclosureMotionFrame,
                completed:=AddressOf CompleteDisclosureMotionFrame)
            _disclosureMotionRunner.Start()

            InvalidateVisual()
        End Sub

        Private Sub ApplyDisclosureMotionFrame(frame As MASMotionFrame)
            If frame Is Nothing Then Return
            _disclosureProgress = MASMotionSystem.ClampProgress(frame.Value)
            _hasDisclosureMotion = True
            InvalidateVisual()
        End Sub

        Private Sub CompleteDisclosureMotionFrame(frame As MASMotionFrame)
            _disclosureProgress = If(_isExpanded, 1.0F, 0.0F)
            _hasDisclosureMotion = False
            _disclosureMotionRunner = Nothing
            InvalidateVisual()
        End Sub

        Private Sub StopDisclosureMotion(resetToCurrentState As Boolean)
            If _disclosureMotionRunner IsNot Nothing Then
                _disclosureMotionRunner.Dispose()
                _disclosureMotionRunner = Nothing
            End If

            If resetToCurrentState Then
                _disclosureProgress = If(_isExpanded, 1.0F, 0.0F)
                _hasDisclosureMotion = False
            End If
        End Sub

        Private Function IsDisclosureMotionActive() As Boolean
            Return _hasDisclosureMotion AndAlso _disclosureMotionRunner IsNot Nothing AndAlso _disclosureMotionRunner.IsRunning
        End Function

        Private Function ResolveDisclosureVisualProgress() As Single
            If _hasDisclosureMotion Then Return MASMotionSystem.ClampProgress(_disclosureProgress)
            Return If(_isExpanded, 1.0F, 0.0F)
        End Function

        Private Function ApplyDisclosureMotionAlpha(color As SKColor) As SKColor
            If Not _hasDisclosureMotion Then Return color

            Dim multiplier As Single = MASMotionSystem.ClampProgress(_disclosureProgress)
            Dim alpha As Integer = CInt(Math.Round(CDbl(color.Alpha) * CDbl(multiplier)))
            If alpha < 0 Then alpha = 0
            If alpha > 255 Then alpha = 255
            Return color.WithAlpha(CByte(alpha))
        End Function

        Private Shared Function Lerp(fromValue As Single,
                                     toValue As Single,
                                     progress As Single) As Single
            Dim p As Single = MASMotionSystem.ClampProgress(progress)
            Return fromValue + ((toValue - fromValue) * p)
        End Function

#End Region

    End Class

End Namespace
