Option Strict On
Option Explicit On

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

Namespace Nexamas.UI.Components

    Friend NotInheritable Class MASAppLayoutLayoutPlan
        Friend Shared ReadOnly Thresholds As New MASResponsiveLayoutThresholds(
            fullWidthDip:=AppLayoutTokens.WideBreakpointDip,
            denseWidthDip:=AppLayoutTokens.MediumBreakpointDip,
            compactWidthDip:=AppLayoutTokens.MinWidthDip,
            minimalWidthDip:=260.0F,
            fullHeightDip:=AppLayoutTokens.PreferredHeightDip,
            denseHeightDip:=AppLayoutTokens.MinHeightDip,
            compactHeightDip:=210.0F,
            minimalHeightDip:=120.0F)

        Friend ReadOnly Property ResponsiveProfile As MASResponsiveLayoutProfile
        Friend ReadOnly Property PixelDpi As Single
        Friend ReadOnly Property MetricDpi As Single
        Friend ReadOnly Property PaddingPx As Single
        Friend ReadOnly Property ModeText As String
        Friend ReadOnly Property ShowNavigation As Boolean
        Friend ReadOnly Property ShowDetails As Boolean
        Friend ReadOnly Property ShowStatusBar As Boolean

        Private Sub New(profile As MASResponsiveLayoutProfile,
                        metricDpi As Single,
                        paddingPx As Single,
                        modeText As String,
                        showNavigation As Boolean,
                        showDetails As Boolean,
                        showStatusBar As Boolean)
            Dim safeProfile As MASResponsiveLayoutProfile = If(profile, MASResponsiveLayoutResolver.FromLogicalSize(MASSizeLayoutIntegrationContext.Empty, SKSize.Empty, MASSize.Default, Thresholds))
            Me.ResponsiveProfile = safeProfile
            Me.PixelDpi = safeProfile.DpiScale
            Me.MetricDpi = Math.Max(0.25F, metricDpi)
            Me.PaddingPx = Math.Max(0.0F, paddingPx)
            Me.ModeText = If(String.IsNullOrWhiteSpace(modeText), "Compact", modeText)
            Me.ShowNavigation = showNavigation
            Me.ShowDetails = showDetails
            Me.ShowStatusBar = showStatusBar
        End Sub

        Friend Shared Function Create(ctx As MASThemeContext,
                                      boundsPx As SKRect,
                                      sizeIntent As MASSize,
                                      requestedNavigation As Boolean,
                                      requestedDetails As Boolean,
                                      requestedStatusBar As Boolean) As MASAppLayoutLayoutPlan
            Dim profile As MASResponsiveLayoutProfile = MASResponsiveLayoutResolver.FromTheme(ctx, boundsPx, sizeIntent, Thresholds)
            Dim metricDpi As Single = profile.DpiScale * ClampScale(profile.ContentScale, 0.66F, 1.24F)
            Dim chromeScale As Single = ClampScale(profile.ChromeScale, 0.62F, 1.22F)
            Dim paddingPx As Single = AppLayoutTokens.PaddingDip * profile.DpiScale * chromeScale

            If profile.IsCollapsed Then paddingPx = Math.Min(paddingPx, 4.0F * profile.DpiScale)

            Dim widthDip As Single = If(profile.AvailableSizeDip.Width > 0.0F, profile.AvailableSizeDip.Width, boundsPx.Width / Math.Max(0.25F, profile.DpiScale))
            Dim modeText As String
            If profile.Mode = MASResponsiveLayoutMode.Collapsed OrElse profile.Mode = MASResponsiveLayoutMode.Minimal Then
                modeText = "Compact"
            ElseIf widthDip < AppLayoutTokens.MediumBreakpointDip Then
                modeText = "Compact"
            ElseIf widthDip < AppLayoutTokens.WideBreakpointDip Then
                modeText = "Balanced"
            Else
                modeText = "Wide"
            End If

            Dim allowNavigation As Boolean = requestedNavigation AndAlso Not profile.IsCollapsed
            Dim allowDetails As Boolean = requestedDetails AndAlso Not profile.IsCompactOrSmaller
            Dim allowStatus As Boolean = requestedStatusBar AndAlso Not profile.IsMinimalOrSmaller

            Return New MASAppLayoutLayoutPlan(profile, metricDpi, paddingPx, modeText, allowNavigation, allowDetails, allowStatus)
        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
            Return Math.Max(minValue, Math.Min(maxValue, value))
        End Function
    End Class

End Namespace
