Option Strict On
Option Explicit On

Imports System
Imports Nexamas.UI.Architecture
Imports Nexamas.UI.Components
Imports Nexamas.UI.Composition
Imports Nexamas.UI.General
Imports Nexamas.UI.Layout
Imports Nexamas.UI.Rendering
Imports Nexamas.UI.Theming
Imports Nexamas.UI.Values
Imports SkiaSharp

Namespace Nexamas.UI.Controls

    Partial Public NotInheritable Class MASProgressBar
#Region "Convenience API"

        Public Sub SetRange(min As Double, max As Double)
            _minimum = NormalizeRangeEndpoint(min, 0.0R)
            _maximum = NormalizeRangeEndpoint(max, 100.0R)
            Dim valueChanged As Boolean = NormalizeRange()
            StopValueMotion(syncToSemanticValue:=True)
            If valueChanged Then RaiseEvent ValueChanged(Me, EventArgs.Empty)
            InvalidateVisual()
        End Sub

        Public Sub SetPercent(percent As Double)
            Value = MASProgressBarValuePolicy.ResolveValueFromPercent(_minimum, _maximum, percent)
        End Sub

        Public Sub Increment(Optional stepValue As Double = 1.0R)
            Value += stepValue
        End Sub

        Public Sub Reset()
            Value = _minimum
        End Sub

        Public Sub Complete()
            Value = _maximum
        End Sub

        Public Sub SetState(state As MASProgressBarState)
            VisualState = state
        End Sub

        ''' <summary>
        ''' Re-applies the current internal layout for the progress track and imported MASLabel.
        ''' This is useful after the caller changes MASLabel properties that influence text presentation.
        ''' </summary>
        Friend Sub RefreshLabelLayout()
            ArrangeLabel()
            InvalidateVisual()
        End Sub

#End Region

#Region "ReadOnly"

        Public ReadOnly Property ProgressFraction As Single
            Get
                Return ResolveProgressFraction(_minimum, _maximum, _value)
            End Get
        End Property

        ''' <summary>
        ''' Returns the logical rectangle currently reserved for the painted progress track inside BoundsLogical.
        ''' </summary>
        Friend ReadOnly Property ProgressBoundsLogical As SKRect
            Get
                Return ResolveTrackBoundsLogical(ResolveProgressSlotBoundsLogical(BoundsLogical))
            End Get
        End Property

        ''' <summary>
        ''' Returns the recommended logical size for this instance, including the active label placement when a label is attached.
        ''' </summary>
        Friend ReadOnly Property RecommendedSize As SKSize
            Get
                Return ResolveRecommendedSize(_sizeMode, ResolveActiveLabelPlacement(), _frameMode)
            End Get
        End Property

#End Region

#Region "SDK Fluent API"

        Public Shared Function Create() As MASProgressBar
            Return New MASProgressBar()
        End Function

        Friend Shared Function [Default]() As MASProgressBar
            Return Create().
                WithRange(0.0R, 100.0R).
                WithValue(0.0R).
                Normal().
                WithSizeMode(MASProgressBarSize.[Default]).
                WithRecommendedSize()
        End Function

        ''' <summary>
        ''' Returns the Nexamas UI recommended logical size for a progress bar preset.
        ''' </summary>
        Friend Shared Function GetRecommendedSize(Optional sizeMode As MASProgressBarSize = MASProgressBarSize.[Default],
                                                  Optional labelPlacement As MASProgressBarLabelPlacement = MASProgressBarLabelPlacement.None,
                                                  Optional frameMode As MASProgressBarFrameMode = MASProgressBarFrameMode.None) As SKSize

            Return ResolveRecommendedSize(NormalizeSizeMode(sizeMode), NormalizeLabelPlacement(labelPlacement), NormalizeFrameMode(frameMode))
        End Function

        Friend Function SetBounds(bounds As SKRect) As MASProgressBar
            SetLocalLayoutBoundsInternal(bounds)
            ArrangeLabel()
            Return Me
        End Function

        Friend Function WithBounds(bounds As SKRect) As MASProgressBar
            Return SetBounds(bounds)
        End Function

        Friend Function WithBounds(x As Single,
                                   y As Single,
                                   width As Single,
                                   height As Single) As MASProgressBar

             SetLocalLayoutBoundsInternal(New SKRect(
                x,
                y,
                x + Math.Max(0.0F, width),
                y + Math.Max(0.0F, height)
            ))

            ArrangeLabel()
            Return Me
        End Function

        Public Function WithRange(min As Double,
                                  max As Double) As MASProgressBar
            SetRange(min, max)
            Return Me
        End Function

        Public Function WithValue(value As Double) As MASProgressBar
            Me.Value = value
            Return Me
        End Function

        Public Function WithPercent(percent As Double) As MASProgressBar
            SetPercent(percent)
            Return Me
        End Function

        Public Function WithState(state As MASProgressBarState) As MASProgressBar
            VisualState = state
            Return Me
        End Function

        Public Function WithLabel(label As MASLabel,
                                  Optional placement As MASProgressBarLabelPlacement = MASProgressBarLabelPlacement.Top) As MASProgressBar
            Me.Label = label
            Me.LabelPlacement = placement
            Return Me
        End Function

        Public Function WithoutLabel() As MASProgressBar
            Me.Label = Nothing
            Me.LabelPlacement = MASProgressBarLabelPlacement.None
            Return Me
        End Function

        Public Function WithLabelPlacement(placement As MASProgressBarLabelPlacement) As MASProgressBar
            Me.LabelPlacement = placement
            Return Me
        End Function

        <Global.System.ComponentModel.EditorBrowsable(Global.System.ComponentModel.EditorBrowsableState.Advanced)>
        Friend Function WithLabelGap(gap As Single) As MASProgressBar
            Me.LabelGap = gap
            Return Me
        End Function

        <Global.System.ComponentModel.EditorBrowsable(Global.System.ComponentModel.EditorBrowsableState.Advanced)>
        Friend Function WithLabelExtent(extent As Single) As MASProgressBar
            Me.LabelExtent = extent
            Return Me
        End Function

        Public Function WithAutoArrangeLabelAlignment(value As Boolean) As MASProgressBar
            Me.AutoArrangeLabelAlignment = value
            Return Me
        End Function

        ''' <summary>
        ''' Strongly typed MASProgressBar entry into the shared MASSize API. This stores the same
        ''' size intent as every MASControlBase element and only mirrors Compact/Default/Large into
        ''' the advanced recommended-track preset so legacy recommended bounds remain coherent.
        ''' </summary>
        Public Shadows Function WithSize(sizeIntent As MASSize) As MASProgressBar
            Dim safeIntent As MASSize = MASSize.Normalize(sizeIntent)
            SetSize(safeIntent)
            SizeMode = MapSizeIntentToProgressBarSize(safeIntent)
            Return Me
        End Function


        ''' <summary>
        ''' Mirrors the shared MASSize gateway into the progress bar's advanced recommendation preset.
        ''' This keeps inherited WithCompactSize/WithDefaultSize/WithLargeSize coherent without adding
        ''' duplicate public concrete preset aliases on MASProgressBar.
        ''' </summary>
        Friend Overrides Sub OnSizeIntentChanged(previousIntent As MASSize,
                                             nextIntent As MASSize)
            MyBase.OnSizeIntentChanged(previousIntent, nextIntent)
            SizeMode = MapSizeIntentToProgressBarSize(nextIntent)
        End Sub






        <Global.System.ComponentModel.EditorBrowsable(Global.System.ComponentModel.EditorBrowsableState.Advanced)>
        Friend Function WithSizeMode(sizeMode As MASProgressBarSize) As MASProgressBar
            Me.SizeMode = sizeMode
            Return Me
        End Function

        Public Function WithFrameMode(frameMode As MASProgressBarFrameMode) As MASProgressBar
            Me.FrameMode = frameMode
            Return Me
        End Function

        Public Function WithContainedField() As MASProgressBar
            Return WithFrameMode(MASProgressBarFrameMode.ContainedField)
        End Function

        Public Function WithoutFrame() As MASProgressBar
            Return WithFrameMode(MASProgressBarFrameMode.None)
        End Function

        Public Function WithContainerSurfaceMaterial(materialKey As String) As MASProgressBar
            Me.ContainerSurfaceMaterialKey = materialKey
            Return Me
        End Function

        Public Function WithContainerStrengths(border As MASSurfaceStrength,
                                               surface As MASSurfaceStrength) As MASProgressBar
            Me.ContainerBorderStrength = border
            Me.ContainerSurfaceStrength = surface
            Return Me
        End Function

        <Global.System.ComponentModel.EditorBrowsable(Global.System.ComponentModel.EditorBrowsableState.Advanced)>
        Friend Function ApplyRecommendedSize(Optional widthOverride As Single = 0.0F) As MASProgressBar
            Dim size As SKSize = RecommendedSize
            Dim width As Single = If(widthOverride > 0.0F, widthOverride, size.Width)

             SetLocalLayoutBoundsInternal(New SKRect(
                BoundsLogical.Left,
                BoundsLogical.Top,
                BoundsLogical.Left + Math.Max(0.0F, width),
                BoundsLogical.Top + Math.Max(0.0F, size.Height)))

            ArrangeLabel()
            Return Me
        End Function

        <Global.System.ComponentModel.EditorBrowsable(Global.System.ComponentModel.EditorBrowsableState.Advanced)>
        Friend Function WithRecommendedSize(Optional sizeMode As MASProgressBarSize = MASProgressBarSize.[Default],
                                            Optional widthOverride As Single = 0.0F) As MASProgressBar
            Me.SizeMode = sizeMode
            Return ApplyRecommendedSize(widthOverride)
        End Function

        <Global.System.ComponentModel.EditorBrowsable(Global.System.ComponentModel.EditorBrowsableState.Advanced)>
        Friend Function WithDefaultRecommendedSize(Optional widthOverride As Single = 0.0F) As MASProgressBar
            Return WithRecommendedSize(MASProgressBarSize.[Default], widthOverride)
        End Function

        <Global.System.ComponentModel.EditorBrowsable(Global.System.ComponentModel.EditorBrowsableState.Advanced)>
        Friend Function WithRecommendedBounds(x As Single,
                                              y As Single,
                                              Optional sizeMode As MASProgressBarSize = MASProgressBarSize.[Default],
                                              Optional widthOverride As Single = 0.0F) As MASProgressBar
            Me.SizeMode = sizeMode

            Dim size As SKSize = RecommendedSize
            Dim width As Single = If(widthOverride > 0.0F, widthOverride, size.Width)

            Return WithBounds(
                x,
                y,
                Math.Max(0.0F, width),
                Math.Max(0.0F, size.Height))
        End Function

        <Global.System.ComponentModel.EditorBrowsable(Global.System.ComponentModel.EditorBrowsableState.Advanced)>
        Friend Function WithDefaultBounds(x As Single,
                                          y As Single,
                                          Optional widthOverride As Single = 0.0F) As MASProgressBar
            Return WithRecommendedBounds(x, y, MASProgressBarSize.[Default], widthOverride)
        End Function

        Public Function Normal() As MASProgressBar
            Return WithState(MASProgressBarState.Normal)
        End Function

        Public Function Success() As MASProgressBar
            Return WithState(MASProgressBarState.Success)
        End Function

        Public Function Warning() As MASProgressBar
            Return WithState(MASProgressBarState.Warning)
        End Function

        Public Function Danger() As MASProgressBar
            Return WithState(MASProgressBarState.Danger)
        End Function

        Public Function IncrementBy(Optional stepValue As Double = 1.0R) As MASProgressBar
            Increment(stepValue)
            Return Me
        End Function

        Public Function ResetProgress() As MASProgressBar
            Reset()
            Return Me
        End Function

        Public Function CompleteProgress() As MASProgressBar
            Complete()
            Return Me
        End Function

        Friend Function OnValueChanged(handler As EventHandler) As MASProgressBar
            If handler IsNot Nothing Then
                AddHandler ValueChanged, handler
            End If

            Return Me
        End Function

        Friend Function OnValueChanged(action As Action(Of MASProgressBar, Double, Single)) As MASProgressBar
            If action Is Nothing Then Return Me

            AddHandler ValueChanged,
                Sub(sender As Object, e As EventArgs)
                    action.Invoke(Me, Value, ProgressFraction)
                End Sub

            Return Me
        End Function

#End Region
    End Class

End Namespace
