Option Strict On
Option Explicit On

Imports Nexamas.UI.Icons
Imports Nexamas.UI.Layout
Imports SkiaSharp

Namespace Nexamas.UI.Rendering

    ''' <summary>
    ''' Internal immutable render contract for PanelShell.
    ''' It is consumed only by Nexamas UI-owned chrome gateways and renderers; external
    ''' projects must use Application-level surfaces rather than constructing shell geometry.
    ''' </summary>
    Friend NotInheritable Class MASPanelShellSpec
        Implements IMASSurfaceLayoutContract

        Friend ReadOnly Property BoundsPx As SKRect
        Friend ReadOnly Property Density As MASPanelShellDensity
        Friend ReadOnly Property Header As MASPanelShellHeaderSpec
        Friend ReadOnly Property BorderStrength As MASPanelShellStrength
        Friend ReadOnly Property SurfaceStrength As MASPanelShellStrength
        Friend ReadOnly Property Padding As MASPanelShellPadding
        Friend ReadOnly Property SurfaceVisualStyleKey As String
        Friend ReadOnly Property SurfaceMaterialKey As String
        Friend ReadOnly Property SurfaceVisualStyle As MASSurfaceVisualStyle

        Friend Sub New(boundsPx As SKRect,
                       Optional density As MASPanelShellDensity = MASPanelShellDensity.Normal,
                       Optional header As MASPanelShellHeaderSpec = Nothing,
                       Optional borderStrength As MASPanelShellStrength = MASPanelShellStrength.ThemeDefault,
                       Optional surfaceStrength As MASPanelShellStrength = MASPanelShellStrength.ThemeDefault,
                       Optional padding As Nullable(Of MASPanelShellPadding) = Nothing,
                       Optional surfaceVisualStyleKey As String = MASSurfaceVisualStyleIds.Auto,
                       Optional surfaceMaterialKey As String = MASSurfaceMaterialIds.Auto,
                       Optional surfaceVisualStyle As MASSurfaceVisualStyle = Nothing)

            Dim safeDensity As MASPanelShellDensity =
                MASPanelShellValueNormalizer.NormalizeDensity(density)

            Me.BoundsPx = MASPanelShellValueNormalizer.NormalizeBoundsPx(boundsPx)
            Me.Density = safeDensity
            Me.Header = If(header, MASPanelShellHeaderSpec.None).WithDensity(safeDensity)
            Me.BorderStrength = MASPanelShellValueNormalizer.NormalizeStrength(borderStrength)
            Me.SurfaceStrength = MASPanelShellValueNormalizer.NormalizeStrength(surfaceStrength)
            Me.Padding = If(padding.HasValue, padding.Value, MASPanelShellPadding.ThemeDefault)
            Me.SurfaceVisualStyleKey = NormalizeVisualStyleKey(surfaceVisualStyleKey)
            Me.SurfaceMaterialKey = NormalizeMaterialKey(surfaceMaterialKey)
            Me.SurfaceVisualStyle = surfaceVisualStyle
        End Sub


#Region "MASSize / Surface Layout Contract"

        Friend Function MeasureSurfaceLayout(context As MASSizeContext,
                                             availableSize As SKSize,
                                             intent As MASSize) As MASSizeResult Implements IMASSurfaceLayoutContract.MeasureSurfaceLayout
            Dim safeContext As MASSizeContext = If(context, New MASSizeContext(ResolveAvailableSurfaceSize(availableSize)))
            Dim characteristics As New MASSurfaceLayoutCharacteristics(hasHeader:=Header IsNot Nothing AndAlso Header.Size <> MASPanelShellHeaderSize.None)

            Return MASSurfaceLayoutSizeResolver.Resolve(
                MASSurfaceLayoutKind.PanelShell,
                safeContext,
                availableSize,
                intent,
                characteristics)
        End Function

        Private Shared Function ResolveAvailableSurfaceSize(availableSize As SKSize) As SKSize
            Dim width As Single = availableSize.Width
            Dim height As Single = availableSize.Height
            If Single.IsNaN(width) OrElse width <= 0.0F OrElse Single.IsNegativeInfinity(width) Then width = Single.PositiveInfinity
            If Single.IsNaN(height) OrElse height <= 0.0F OrElse Single.IsNegativeInfinity(height) Then height = Single.PositiveInfinity
            Return New SKSize(width, height)
        End Function

#End Region

        Friend Shared Function Create(boundsPx As SKRect) As MASPanelShellBuilder
            Return New MASPanelShellBuilder(boundsPx)
        End Function

        Friend Shared Function FromBounds(boundsPx As SKRect) As MASPanelShellSpec
            Return New MASPanelShellSpec(boundsPx:=boundsPx)
        End Function

        Friend Function WithBounds(boundsPx As SKRect) As MASPanelShellSpec
            Return Copy(boundsPx:=boundsPx)
        End Function

        Friend Function WithDensity(value As MASPanelShellDensity) As MASPanelShellSpec
            Dim safeDensity As MASPanelShellDensity =
                MASPanelShellValueNormalizer.NormalizeDensity(value)

            Return Copy(density:=safeDensity,
                        header:=Header.WithDensity(safeDensity))
        End Function

        Friend Function WithHeader(headerSpec As MASPanelShellHeaderSpec) As MASPanelShellSpec
            Return Copy(header:=If(headerSpec, MASPanelShellHeaderSpec.None).WithDensity(Density))
        End Function

        Friend Function WithoutHeader() As MASPanelShellSpec
            Return Copy(header:=MASPanelShellHeaderSpec.None.WithDensity(Density))
        End Function

        Friend Function WithHeader(title As String,
                                   Optional subtitle As String = "",
                                   Optional iconKind As MASIconKind = MASIconKind.Info,
                                   Optional showIcon As Boolean = False,
                                   Optional showCloseButton As Boolean = False,
                                   Optional size As MASPanelShellHeaderSize = MASPanelShellHeaderSize.Normal) As MASPanelShellSpec

            Dim headerSpec As MASPanelShellHeaderSpec =
                MASPanelShellHeaderSpec.Create(
                    title:=title,
                    subtitle:=subtitle,
                    iconKind:=iconKind,
                    showIcon:=showIcon,
                    showCloseButton:=showCloseButton,
                    size:=size,
                    density:=Density)

            Return Copy(header:=headerSpec)
        End Function

        Friend Function WithHeaderSize(value As MASPanelShellHeaderSize) As MASPanelShellSpec
            Return Copy(header:=Header.WithSize(MASPanelShellValueNormalizer.NormalizeHeaderSize(value)))
        End Function

        Friend Function WithStrengths(border As MASPanelShellStrength,
                                      surface As MASPanelShellStrength) As MASPanelShellSpec
            Return Copy(
                borderStrength:=MASPanelShellValueNormalizer.NormalizeStrength(border),
                surfaceStrength:=MASPanelShellValueNormalizer.NormalizeStrength(surface))
        End Function

        Friend Function WithBorderStrength(value As MASPanelShellStrength) As MASPanelShellSpec
            Return Copy(borderStrength:=MASPanelShellValueNormalizer.NormalizeStrength(value))
        End Function

        Friend Function WithSurfaceStrength(value As MASPanelShellStrength) As MASPanelShellSpec
            Return Copy(surfaceStrength:=MASPanelShellValueNormalizer.NormalizeStrength(value))
        End Function


        Friend Function WithSurfaceVisualStyleKey(styleKey As String) As MASPanelShellSpec
            Return Copy(surfaceVisualStyleKey:=styleKey, surfaceVisualStyle:=Nothing)
        End Function

        Friend Function WithSurfaceVisualStyle(style As MASSurfaceVisualStyle) As MASPanelShellSpec
            If style Is Nothing Then Return Copy(surfaceVisualStyleKey:=MASSurfaceVisualStyleIds.Auto, surfaceVisualStyle:=Nothing)
            Return Copy(surfaceVisualStyleKey:=style.Id, surfaceVisualStyle:=style)
        End Function

        Friend Function WithSurfaceMaterialKey(materialKey As String) As MASPanelShellSpec
            Return Copy(surfaceMaterialKey:=materialKey)
        End Function

        Friend Function WithPadding(allDip As Single) As MASPanelShellSpec
            Return Copy(padding:=MASPanelShellPadding.All(allDip))
        End Function

        Friend Function WithPadding(horizontalDip As Single,
                                    verticalDip As Single) As MASPanelShellSpec
            Return Copy(padding:=MASPanelShellPadding.Symmetric(horizontalDip, verticalDip))
        End Function

        Friend Function WithPadding(leftDip As Single,
                                    topDip As Single,
                                    rightDip As Single,
                                    bottomDip As Single) As MASPanelShellSpec
            Return Copy(padding:=New MASPanelShellPadding(leftDip, topDip, rightDip, bottomDip))
        End Function

        Friend Function Copy(Optional boundsPx As SKRect? = Nothing,
                             Optional density As MASPanelShellDensity? = Nothing,
                             Optional header As MASPanelShellHeaderSpec = Nothing,
                             Optional borderStrength As MASPanelShellStrength? = Nothing,
                             Optional surfaceStrength As MASPanelShellStrength? = Nothing,
                             Optional padding As MASPanelShellPadding? = Nothing,
                             Optional surfaceVisualStyleKey As String = Nothing,
                             Optional surfaceMaterialKey As String = Nothing,
                             Optional surfaceVisualStyle As MASSurfaceVisualStyle = Nothing) As MASPanelShellSpec

            Dim resolvedDensity As MASPanelShellDensity =
                MASPanelShellValueNormalizer.NormalizeDensity(If(density.HasValue, density.Value, Me.Density))
            Dim resolvedHeader As MASPanelShellHeaderSpec = If(header, Me.Header).WithDensity(resolvedDensity)

            Dim visualStyleKeyWasProvided As Boolean = (surfaceVisualStyleKey IsNot Nothing)
            Dim materialKeyWasProvided As Boolean = (surfaceMaterialKey IsNot Nothing)

            Return New MASPanelShellSpec(
                boundsPx:=If(boundsPx.HasValue, boundsPx.Value, Me.BoundsPx),
                density:=resolvedDensity,
                header:=resolvedHeader,
                borderStrength:=If(borderStrength.HasValue, borderStrength.Value, Me.BorderStrength),
                surfaceStrength:=If(surfaceStrength.HasValue, surfaceStrength.Value, Me.SurfaceStrength),
                padding:=If(padding.HasValue, padding.Value, Me.Padding),
                surfaceVisualStyleKey:=If(visualStyleKeyWasProvided, NormalizeVisualStyleKey(surfaceVisualStyleKey), Me.SurfaceVisualStyleKey),
                surfaceMaterialKey:=If(materialKeyWasProvided, NormalizeMaterialKey(surfaceMaterialKey), Me.SurfaceMaterialKey),
                surfaceVisualStyle:=If(visualStyleKeyWasProvided, surfaceVisualStyle, If(surfaceVisualStyle IsNot Nothing, surfaceVisualStyle, Me.SurfaceVisualStyle)))
        End Function


        Private Shared Function NormalizeVisualStyleKey(value As String) As String
            Return MASPanelShellValueNormalizer.NormalizeKey(value, MASSurfaceVisualStyleIds.Auto)
        End Function

        Private Shared Function NormalizeMaterialKey(value As String) As String
            Return MASPanelShellValueNormalizer.NormalizeKey(value, MASSurfaceMaterialIds.Auto)
        End Function

    End Class

End Namespace
