Option Strict On
Option Explicit On

Imports System
Imports Nexamas.UI.Layout
Imports Nexamas.UI.Theming
Imports Nexamas.UI.Values
Imports SkiaSharp

Namespace Nexamas.UI.Components

    ''' <summary>
    ''' Internal responsive layout facts for MASTileBox grid metrics, virtualization, and hit-testing.
    ''' </summary>
    Friend NotInheritable Class MASTileBoxLayoutPlan
        Friend Shared ReadOnly Thresholds As New MASResponsiveLayoutThresholds(
            fullWidthDip:=360.0F,
            denseWidthDip:=270.0F,
            compactWidthDip:=180.0F,
            minimalWidthDip:=96.0F,
            fullHeightDip:=260.0F,
            denseHeightDip:=190.0F,
            compactHeightDip:=112.0F,
            minimalHeightDip:=56.0F)

        Friend ReadOnly Property ResponsiveProfile As MASResponsiveLayoutProfile
        Friend ReadOnly Property Dpi As Single
        Friend ReadOnly Property MetricScale As Single
        Friend ReadOnly Property TileSizePx As Single
        Friend ReadOnly Property SafeInsetPx As Single
        Friend ReadOnly Property MinGapXPx As Single
        Friend ReadOnly Property MaxGapXPx As Single
        Friend ReadOnly Property GapYPx As Single
        Friend ReadOnly Property MinWorkSizePx As Single
        Friend ReadOnly Property IsCollapsed As Boolean

        Private Sub New(profile As MASResponsiveLayoutProfile,
                        metricScale As Single,
                        tileSizePx As Single,
                        safeInsetPx As Single,
                        minGapXPx As Single,
                        maxGapXPx As Single,
                        gapYPx As Single,
                        minWorkSizePx As Single)
            Dim safeProfile As MASResponsiveLayoutProfile = If(profile, MASResponsiveLayoutResolver.FromLogicalSize(MASSizeLayoutIntegrationContext.Empty, SKSize.Empty, MASSize.Default, Thresholds))
            Me.ResponsiveProfile = safeProfile
            Me.Dpi = safeProfile.DpiScale
            Me.MetricScale = Math.Max(0.62F, Math.Min(1.28F, metricScale))
            Me.TileSizePx = Math.Max(1.0F, tileSizePx)
            Me.SafeInsetPx = Math.Max(0.0F, safeInsetPx)
            Me.MinGapXPx = Math.Max(0.0F, minGapXPx)
            Me.MaxGapXPx = Math.Max(Me.MinGapXPx, maxGapXPx)
            Me.GapYPx = Math.Max(0.0F, gapYPx)
            Me.MinWorkSizePx = Math.Max(1.0F, minWorkSizePx)
            Me.IsCollapsed = safeProfile.Mode = MASResponsiveLayoutMode.Collapsed
        End Sub

        Friend Shared Function Create(ctx As MASThemeContext,
                                      availableBoundsPx As SKRect,
                                      sizeIntent As MASSize) As MASTileBoxLayoutPlan
            Return Create(MASResponsiveLayoutResolver.FromTheme(ctx, availableBoundsPx, sizeIntent, Thresholds))
        End Function

        Friend Shared Function Create(profile As MASResponsiveLayoutProfile) As MASTileBoxLayoutPlan
            Dim safeProfile As MASResponsiveLayoutProfile = If(profile, MASResponsiveLayoutResolver.FromLogicalSize(MASSizeLayoutIntegrationContext.Empty, SKSize.Empty, MASSize.Default, Thresholds))
            Dim contentScale As Single = ClampScale(safeProfile.ContentScale, 0.62F, 1.28F)
            Dim gapScale As Single = ClampScale(safeProfile.GapScale, 0.55F, 1.2F)
            Dim chromeScale As Single = ClampScale(safeProfile.ChromeScale, 0.62F, 1.24F)

            If safeProfile.Mode = MASResponsiveLayoutMode.Collapsed Then
                contentScale = Math.Min(contentScale, 0.66F)
                gapScale = Math.Min(gapScale, 0.58F)
                chromeScale = Math.Min(chromeScale, 0.66F)
            End If

            Dim tilePx As Single = 92.0F * safeProfile.DpiScale * contentScale
            Dim minTilePx As Single = If(safeProfile.Mode = MASResponsiveLayoutMode.Collapsed, 44.0F, If(safeProfile.Mode = MASResponsiveLayoutMode.Minimal, 56.0F, 72.0F)) * safeProfile.DpiScale
            tilePx = Math.Max(minTilePx, tilePx)

            Return New MASTileBoxLayoutPlan(
                profile:=safeProfile,
                metricScale:=contentScale,
                tileSizePx:=tilePx,
                safeInsetPx:=8.0F * safeProfile.DpiScale * chromeScale,
                minGapXPx:=10.0F * safeProfile.DpiScale * gapScale,
                maxGapXPx:=28.0F * safeProfile.DpiScale * gapScale,
                gapYPx:=14.0F * safeProfile.DpiScale * gapScale,
                minWorkSizePx:=If(safeProfile.Mode = MASResponsiveLayoutMode.Collapsed, 18.0F, 40.0F) * safeProfile.DpiScale)
        End Function

        Private Shared Function ClampScale(value As Single, minValue As Single, maxValue As Single) As Single
            If Single.IsNaN(value) OrElse Single.IsInfinity(value) OrElse value <= 0.0F Then Return 1.0F
            If value < minValue Then Return minValue
            If value > maxValue Then Return maxValue
            Return value
        End Function
    End Class

End Namespace
