Option Strict On
Option Explicit On

Imports System
Imports System.ComponentModel
Imports System.Globalization
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 MASOperationProgressBox
#Region "Factories"

        Public Shared Function Create(Optional titleText As String = Nothing,
                                      Optional statusText As String = Nothing) As MASOperationProgressBox

            Dim box As New MASOperationProgressBox()

            If titleText IsNot Nothing Then box.TitleText = titleText
            If statusText IsNot Nothing Then box.StatusText = statusText

            Return box
        End Function

        Friend Shared Function [Default]() As MASOperationProgressBox
            Return Create().WithRecommendedSize()
        End Function

#End Region

#Region "Core Properties"

        Public Property TitleText As String
            Get
                Return _titleText
            End Get
            Set(value As String)
                Dim nextValue As String = MASOperationProgressBoxPolicy.NormalizeTitleText(value)
                If String.Equals(_titleText, nextValue, StringComparison.Ordinal) Then Return

                _titleText = nextValue
                _titleLabel.Text = _titleText
                ArrangeChildren()
                InvalidateVisual()
            End Set
        End Property

        Public Property StatusText As String
            Get
                Return _statusText
            End Get
            Set(value As String)
                Dim nextValue As String = MASOperationProgressBoxPolicy.NormalizeStatusText(value)
                If String.Equals(_statusText, nextValue, StringComparison.Ordinal) Then Return

                _statusText = nextValue
                _statusLabel.Text = _statusText
                ArrangeChildren()
                InvalidateVisual()
            End Set
        End Property

        Public Property Minimum As Double
            Get
                Return _minimum
            End Get
            Set(value As Double)
                Dim nextMinimum As Double = NormalizeRangeEndpoint(value, 0.0R)
                If NearlyEqual(_minimum, nextMinimum) Then Return

                _minimum = nextMinimum
                Dim valueChanged As Boolean = NormalizeRange()
                SyncProgressBar()
                If valueChanged Then RaiseEvent ValueChanged(Me, EventArgs.Empty)
                InvalidateVisual()
            End Set
        End Property

        Public Property Maximum As Double
            Get
                Return _maximum
            End Get
            Set(value As Double)
                Dim nextMaximum As Double = NormalizeRangeEndpoint(value, 100.0R)
                If NearlyEqual(_maximum, nextMaximum) Then Return

                _maximum = nextMaximum
                Dim valueChanged As Boolean = NormalizeRange()
                SyncProgressBar()
                If valueChanged Then RaiseEvent ValueChanged(Me, EventArgs.Empty)
                InvalidateVisual()
            End Set
        End Property

        Public Property Value As Double
            Get
                Return _value
            End Get
            Set(v As Double)
                Dim nextValue As Double = MASProgressBarValuePolicy.NormalizeValue(v, _minimum, _maximum)
                If Math.Abs(_value - nextValue) < 0.0000001R Then Return

                _value = nextValue
                SyncProgressBar()
                RaiseEvent ValueChanged(Me, EventArgs.Empty)
                InvalidateVisual()
            End Set
        End Property

        Public Property VisualState As MASProgressBarState
            Get
                Return _visualState
            End Get
            Set(value As MASProgressBarState)
                Dim nextState As MASProgressBarState = MASProgressBarValuePolicy.NormalizeVisualState(value)
                If _visualState = nextState Then Return

                _visualState = nextState
                _progressBar.VisualState = nextState
                InvalidateVisual()
            End Set
        End Property

        ''' <summary>
        ''' Surface material used by the outer operation container. The default is PlatformDefault.
        ''' The inner progress bar keeps its own IMASProgressTheme pipeline.
        ''' </summary>
        Public Property ContainerSurfaceMaterialKey As String
            Get
                Return _containerSurfaceMaterialKey
            End Get
            Set(value As String)
                Dim nextValue As String = NormalizeMaterialKey(value)
                If String.Equals(_containerSurfaceMaterialKey, nextValue, StringComparison.OrdinalIgnoreCase) Then Return

                _containerSurfaceMaterialKey = nextValue
                InvalidateVisual()
            End Set
        End Property

        Public Property ContainerBorderStrength As MASSurfaceStrength
            Get
                Return _containerBorderStrength
            End Get
            Set(value As MASSurfaceStrength)
                Dim nextValue As MASSurfaceStrength = NormalizeSurfaceStrength(value)
                If _containerBorderStrength = nextValue Then Return

                _containerBorderStrength = nextValue
                InvalidateVisual()
            End Set
        End Property

        Public Property ContainerSurfaceStrength As MASSurfaceStrength
            Get
                Return _containerSurfaceStrength
            End Get
            Set(value As MASSurfaceStrength)
                Dim nextValue As MASSurfaceStrength = NormalizeSurfaceStrength(value)
                If _containerSurfaceStrength = nextValue Then Return

                _containerSurfaceStrength = nextValue
                InvalidateVisual()
            End Set
        End Property

#End Region

#Region "ReadOnly"

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

        Public ReadOnly Property RecommendedSize As SKSize
            Get
                Return OperationProgressBoxTokens.DefaultSize
            End Get
        End Property

#End Region

#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()
            SyncProgressBar()
            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

#End Region

#Region "Fluent API"

        Friend Function WithBounds(bounds As SKRect) As MASOperationProgressBox
            SetLocalLayoutBoundsInternal(bounds)
            ArrangeChildren()
            Return Me
        End Function

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

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

            ArrangeChildren()
            Return Me
        End Function

        <EditorBrowsable(EditorBrowsableState.Advanced)>
        Friend Function WithRecommendedSize(Optional widthOverride As Single = 0.0F) As MASOperationProgressBox
            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(OperationProgressBoxTokens.MinWidth, width),
                BoundsLogical.Top + size.Height))

            ArrangeChildren()
            Return Me
        End Function

        <EditorBrowsable(EditorBrowsableState.Advanced)>
        Friend Function WithRecommendedBounds(x As Single,
                                              y As Single,
                                              Optional widthOverride As Single = 0.0F) As MASOperationProgressBox

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

            Return WithBounds(
                x,
                y,
                Math.Max(OperationProgressBoxTokens.MinWidth, width),
                size.Height)
        End Function

        Public Function WithTitle(text As String) As MASOperationProgressBox
            TitleText = text
            Return Me
        End Function

        Public Function WithStatus(text As String) As MASOperationProgressBox
            StatusText = text
            Return Me
        End Function

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

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

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

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

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

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

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

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

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

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

#End Region

#Region "Unified MASSize Fluent API"

        ''' <summary>
        ''' Strongly typed entry into the shared MASSize intent API.
        ''' This method keeps fluent chains on the concrete element while delegating all sizing decisions to MASControlBase/MASSize.
        ''' </summary>
        Public Shadows Function WithSize(sizeIntent As Nexamas.UI.Layout.MASSize) As MASOperationProgressBox
            MyBase.SetSize(sizeIntent)
            Return Me
        End Function






#End Region
    End Class

End Namespace
