Option Strict On
Option Explicit On

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

Namespace Nexamas.UI.Controls

    ''' <summary>
    ''' Public MAS-prefixed group box surface source contract used by MASGroupBox.
    ''' </summary>
    Public Enum MASGroupBoxSurfaceSource
        Acrylic = 0
        Plain = 1
        TransparentFrame = 2
    End Enum

    ''' <summary>
    ''' Public MAS-prefixed group box border recipe contract used by MASGroupBox.
    ''' </summary>
    Public Enum MASGroupBoxBorderRecipe
        ListSurface = 0
        AcrylicSurface = 1
    End Enum

    ''' <summary>
    ''' Public MAS-prefixed group box border strength contract used by MASGroupBox.
    ''' </summary>
    Public Enum MASGroupBoxBorderStrength
        Level1 = 1
        Level2 = 2
        Level3 = 3
        Level4 = 4
        Level5 = 5
        Level6 = 6
    End Enum

    ''' <summary>
    ''' Public MAS-prefixed title plate strength contract used by MASGroupBox.
    ''' </summary>
    Public Enum MASGroupBoxTitlePlateStrength
        Soft = 0
        Premium = 1
        Strong = 2
    End Enum

    ' =========================================================
    ' Contract:
    ' - Pure Skia Nexamas UI container surface; not an overlay by itself.
    ' - Child controls are hosted only through ChildLayerInternal/Controls.
    ' - Header/title, body, border, and shadow must resolve from the shared
    '   GroupBox token/radius/material system.
    ' =========================================================
    Partial Public NotInheritable Class MASGroupBox
        Inherits MASControlBase
        Implements IMASIntrinsicSizeContract
        Implements IMASSurfaceLayoutContract
        Implements IMASLayoutParticipant

        Private ReadOnly _contract As MASResolvedComponentContract =
    MASArchitectureRuntime.ResolveContractOrThrow(GetType(MASGroupBox))

        Private ReadOnly _renderer As New MASGroupBoxRenderer()

        Private _title As String = String.Empty
        Private _surfaceSource As MASGroupBoxSurfaceSource = MASGroupBoxSurfaceSource.Acrylic
        Private _borderRecipe As MASGroupBoxBorderRecipe = MASGroupBoxBorderRecipe.ListSurface
        Private _borderStrength As MASGroupBoxBorderStrength = MASGroupBoxBorderStrength.Level5
        Private _surfaceMaterialKey As String = MASSurfaceMaterialIds.Auto

        Private _drawShadow As Boolean = True
        Private _drawSeparator As Boolean = False
        Private _drawPremiumBorder As Boolean = True
        Private _reserveHeaderWhenEmpty As Boolean = True

        Private _paddingLeft As Single = GroupBoxTokens.PaddingLeft
        Private _paddingTop As Single = GroupBoxTokens.PaddingTop
        Private _paddingRight As Single = GroupBoxTokens.PaddingRight
        Private _paddingBottom As Single = GroupBoxTokens.PaddingBottom
        Private ReadOnly _relativeChildBounds As New Dictionary(Of MASControlBase, SKRect)()

        Public Sub New()
            MyBase.New()
        End Sub


        Public Sub New(title As String)
            MyBase.New()
            _title = MASGroupBoxSurfacePolicy.NormalizeTitle(title)
        End Sub

        Public Property Title As String
            Get
                Return _title
            End Get
            Set(value As String)
                Dim s As String = MASGroupBoxSurfacePolicy.NormalizeTitle(value)
                If String.Equals(_title, s, StringComparison.Ordinal) Then Return

                _title = s
                RaiseTextChanged()
                InvalidateVisual()
            End Set
        End Property

        Public Property SurfaceSource As MASGroupBoxSurfaceSource
            Get
                Return _surfaceSource
            End Get
            Set(value As MASGroupBoxSurfaceSource)
                Dim normalized As MASGroupBoxSurfaceSource = MASGroupBoxSurfacePolicy.NormalizeSurfaceSource(value)
                If _surfaceSource = normalized Then Return
                _surfaceSource = normalized
                InvalidateVisual()
            End Set
        End Property

        Public Property BorderRecipe As MASGroupBoxBorderRecipe
            Get
                Return _borderRecipe
            End Get
            Set(value As MASGroupBoxBorderRecipe)
                Dim normalized As MASGroupBoxBorderRecipe = MASGroupBoxSurfacePolicy.NormalizeBorderRecipe(value)
                If _borderRecipe = normalized Then Return
                _borderRecipe = normalized
                InvalidateVisual()
            End Set
        End Property

        Public Property BorderStrength As MASGroupBoxBorderStrength
            Get
                Return _borderStrength
            End Get
            Set(value As MASGroupBoxBorderStrength)
                Dim normalized As MASGroupBoxBorderStrength = MASGroupBoxSurfacePolicy.NormalizeBorderStrength(value)
                If _borderStrength = normalized Then Return
                _borderStrength = normalized
                InvalidateVisual()
            End Set
        End Property

        Public Property SurfaceMaterial As String
            Get
                Return _surfaceMaterialKey
            End Get
            Set(value As String)
                Dim key As String = MASGroupBoxSurfacePolicy.NormalizeSurfaceMaterial(value)
                If String.Equals(_surfaceMaterialKey, key, StringComparison.OrdinalIgnoreCase) Then Return
                _surfaceMaterialKey = key
                InvalidateVisual()
            End Set
        End Property

        Public Property DrawPremiumBorder As Boolean
            Get
                Return _drawPremiumBorder
            End Get
            Set(value As Boolean)
                If _drawPremiumBorder = value Then Return
                _drawPremiumBorder = value
                InvalidateVisual()
            End Set
        End Property

        Public Property DrawShadow As Boolean
            Get
                Return _drawShadow
            End Get
            Set(value As Boolean)
                If _drawShadow = value Then Return
                _drawShadow = value
                InvalidateVisual()
            End Set
        End Property

        Public Property DrawSeparator As Boolean
            Get
                Return _drawSeparator
            End Get
            Set(value As Boolean)
                If _drawSeparator = value Then Return
                _drawSeparator = value
                InvalidateVisual()
            End Set
        End Property

        Public Property ReserveHeaderWhenEmpty As Boolean
            Get
                Return _reserveHeaderWhenEmpty
            End Get
            Set(value As Boolean)
                If _reserveHeaderWhenEmpty = value Then Return
                _reserveHeaderWhenEmpty = value
                RequestSizeLayoutRefreshForSizeAffectingChange("MASGroupBox.ReserveHeaderWhenEmpty")
                InvalidateVisual()
            End Set
        End Property

        <Global.System.ComponentModel.EditorBrowsable(Global.System.ComponentModel.EditorBrowsableState.Advanced)>
        Friend Property PaddingLeft As Single
            Get
                Return _paddingLeft
            End Get
            Set(value As Single)
                Dim v As Single = MASGroupBoxSurfacePolicy.NormalizePadding(value)
                If Math.Abs(_paddingLeft - v) < 0.001F Then Return
                _paddingLeft = v
                RequestSizeLayoutRefreshForSizeAffectingChange("MASGroupBox.PaddingLeft")
                InvalidateVisual()
            End Set
        End Property

        <Global.System.ComponentModel.EditorBrowsable(Global.System.ComponentModel.EditorBrowsableState.Advanced)>
        Friend Property PaddingTop As Single
            Get
                Return _paddingTop
            End Get
            Set(value As Single)
                Dim v As Single = MASGroupBoxSurfacePolicy.NormalizePadding(value)
                If Math.Abs(_paddingTop - v) < 0.001F Then Return
                _paddingTop = v
                RequestSizeLayoutRefreshForSizeAffectingChange("MASGroupBox.PaddingTop")
                InvalidateVisual()
            End Set
        End Property

        <Global.System.ComponentModel.EditorBrowsable(Global.System.ComponentModel.EditorBrowsableState.Advanced)>
        Friend Property PaddingRight As Single
            Get
                Return _paddingRight
            End Get
            Set(value As Single)
                Dim v As Single = MASGroupBoxSurfacePolicy.NormalizePadding(value)
                If Math.Abs(_paddingRight - v) < 0.001F Then Return
                _paddingRight = v
                RequestSizeLayoutRefreshForSizeAffectingChange("MASGroupBox.PaddingRight")
                InvalidateVisual()
            End Set
        End Property

        <Global.System.ComponentModel.EditorBrowsable(Global.System.ComponentModel.EditorBrowsableState.Advanced)>
        Friend Property PaddingBottom As Single
            Get
                Return _paddingBottom
            End Get
            Set(value As Single)
                Dim v As Single = MASGroupBoxSurfacePolicy.NormalizePadding(value)
                If Math.Abs(_paddingBottom - v) < 0.001F Then Return
                _paddingBottom = v
                RequestSizeLayoutRefreshForSizeAffectingChange("MASGroupBox.PaddingBottom")
                InvalidateVisual()
            End Set
        End Property


        Friend Function CreateGroupBoxReadinessManifest() As MASGroupBoxReadinessManifest
            Return MASGroupBoxReadinessManifest.CreateCurrent()
        End Function

    End Class

End Namespace
