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.Controls

    ''' <summary>
    ''' Internal responsive layout facts for the command palette popup surface.
    ''' Keeps the floating palette chrome, search field, row metrics, and viewport capacity
    ''' tied to Runtime SizeProfile + SizeIntent + AvailableBounds.
    ''' </summary>
    Friend NotInheritable Class MASCommandPaletteLayoutPlan
        Friend Shared ReadOnly Thresholds As New MASResponsiveLayoutThresholds(
            fullWidthDip:=520.0F,
            denseWidthDip:=420.0F,
            compactWidthDip:=300.0F,
            minimalWidthDip:=190.0F,
            fullHeightDip:=420.0F,
            denseHeightDip:=320.0F,
            compactHeightDip:=220.0F,
            minimalHeightDip:=126.0F)

        Friend ReadOnly Property ResponsiveProfile As MASResponsiveLayoutProfile
        Friend ReadOnly Property Dpi As Single
        Friend ReadOnly Property MetricDpi As Single
        Friend ReadOnly Property PaddingPx As Single
        Friend ReadOnly Property HeaderHeightPx As Single
        Friend ReadOnly Property HeaderSearchGapPx As Single
        Friend ReadOnly Property SearchHeightPx As Single
        Friend ReadOnly Property SearchResultsGapPx As Single
        Friend ReadOnly Property RowHeightPx As Single
        Friend ReadOnly Property RowGapPx As Single
        Friend ReadOnly Property RowPaddingHorizontalPx As Single
        Friend ReadOnly Property RowPaddingVerticalPx As Single
        Friend ReadOnly Property CategoryWidthPx As Single
        Friend ReadOnly Property ShortcutWidthPx As Single
        Friend ReadOnly Property CornerRadiusPx As Single
        Friend ReadOnly Property SearchRadiusPx As Single
        Friend ReadOnly Property RowRadiusPx As Single
        Friend ReadOnly Property StrokePx As Single
        Friend ReadOnly Property FocusStrokePx As Single
        Friend ReadOnly Property ShowHeader As Boolean
        Friend ReadOnly Property ShowMetadata As Boolean
        Friend ReadOnly Property ShowCategory As Boolean
        Friend ReadOnly Property ShowShortcut As Boolean
        Friend ReadOnly Property ShowDescription As Boolean
        Friend ReadOnly Property IsCollapsed As Boolean

        Private Sub New(profile As MASResponsiveLayoutProfile,
                        paddingPx As Single,
                        headerHeightPx As Single,
                        headerSearchGapPx As Single,
                        searchHeightPx As Single,
                        searchResultsGapPx As Single,
                        rowHeightPx As Single,
                        rowGapPx As Single,
                        rowPaddingHorizontalPx As Single,
                        rowPaddingVerticalPx As Single,
                        categoryWidthPx As Single,
                        shortcutWidthPx As Single,
                        cornerRadiusPx As Single,
                        searchRadiusPx As Single,
                        rowRadiusPx As Single,
                        strokePx As Single,
                        focusStrokePx As Single,
                        showHeader As Boolean,
                        showMetadata As Boolean,
                        showCategory As Boolean,
                        showShortcut As Boolean,
                        showDescription As Boolean)
            Dim safeProfile As MASResponsiveLayoutProfile = If(profile, CreateFallbackProfile())
            Me.ResponsiveProfile = safeProfile
            Me.Dpi = safeProfile.DpiScale
            Me.MetricDpi = safeProfile.DpiScale * ClampScale(safeProfile.ContentScale, 0.64F, 1.28F)
            Me.PaddingPx = Math.Max(0.0F, paddingPx)
            Me.HeaderHeightPx = Math.Max(0.0F, headerHeightPx)
            Me.HeaderSearchGapPx = Math.Max(0.0F, headerSearchGapPx)
            Me.SearchHeightPx = Math.Max(1.0F, searchHeightPx)
            Me.SearchResultsGapPx = Math.Max(0.0F, searchResultsGapPx)
            Me.RowHeightPx = Math.Max(1.0F, rowHeightPx)
            Me.RowGapPx = Math.Max(0.0F, rowGapPx)
            Me.RowPaddingHorizontalPx = Math.Max(0.0F, rowPaddingHorizontalPx)
            Me.RowPaddingVerticalPx = Math.Max(0.0F, rowPaddingVerticalPx)
            Me.CategoryWidthPx = Math.Max(0.0F, categoryWidthPx)
            Me.ShortcutWidthPx = Math.Max(0.0F, shortcutWidthPx)
            Me.CornerRadiusPx = Math.Max(1.0F, cornerRadiusPx)
            Me.SearchRadiusPx = Math.Max(1.0F, searchRadiusPx)
            Me.RowRadiusPx = Math.Max(1.0F, rowRadiusPx)
            Me.StrokePx = Math.Max(1.0F, strokePx)
            Me.FocusStrokePx = Math.Max(Me.StrokePx, focusStrokePx)
            Me.ShowHeader = showHeader
            Me.ShowMetadata = showMetadata
            Me.ShowCategory = showCategory
            Me.ShowShortcut = showShortcut
            Me.ShowDescription = showDescription
            Me.IsCollapsed = safeProfile.Mode = MASResponsiveLayoutMode.Collapsed
        End Sub

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

        Friend Shared Function Create(profile As MASResponsiveLayoutProfile) As MASCommandPaletteLayoutPlan
            Dim safeProfile As MASResponsiveLayoutProfile = If(profile, CreateFallbackProfile())
            Dim chrome As Single = ClampScale(safeProfile.ChromeScale, 0.62F, 1.28F)
            Dim gap As Single = ClampScale(safeProfile.GapScale, 0.52F, 1.24F)
            Dim content As Single = ClampScale(safeProfile.ContentScale, 0.62F, 1.3F)

            If safeProfile.Mode = MASResponsiveLayoutMode.Collapsed Then
                chrome = Math.Min(chrome, 0.66F)
                gap = Math.Min(gap, 0.56F)
                content = Math.Min(content, 0.72F)
            End If

            Dim showHeader As Boolean = safeProfile.Mode <> MASResponsiveLayoutMode.Collapsed
            Dim showMetadata As Boolean = CInt(safeProfile.Mode) <= CInt(MASResponsiveLayoutMode.Dense)
            Dim showCategory As Boolean = CInt(safeProfile.Mode) <= CInt(MASResponsiveLayoutMode.Compact)
            Dim showShortcut As Boolean = CInt(safeProfile.Mode) <= CInt(MASResponsiveLayoutMode.Dense)
            Dim showDescription As Boolean = CInt(safeProfile.Mode) <= CInt(MASResponsiveLayoutMode.Compact)

            Return New MASCommandPaletteLayoutPlan(
                profile:=safeProfile,
                paddingPx:=safeProfile.ChromeDipToPx(CommandPaletteTokens.PaddingDip),
                headerHeightPx:=If(showHeader, safeProfile.ChromeDipToPx(CommandPaletteTokens.HeaderHeightDip), 0.0F),
                headerSearchGapPx:=If(showHeader, safeProfile.GapDipToPx(CommandPaletteTokens.HeaderSearchGapDip), 0.0F),
                searchHeightPx:=safeProfile.ChromeDipToPx(CommandPaletteTokens.SearchHeightDip),
                searchResultsGapPx:=safeProfile.GapDipToPx(CommandPaletteTokens.SearchResultsGapDip),
                rowHeightPx:=safeProfile.ContentDipToPx(CommandPaletteTokens.RowHeightDip),
                rowGapPx:=safeProfile.GapDipToPx(CommandPaletteTokens.RowGapDip),
                rowPaddingHorizontalPx:=safeProfile.GapDipToPx(CommandPaletteTokens.RowPaddingHorizontalDip),
                rowPaddingVerticalPx:=safeProfile.GapDipToPx(CommandPaletteTokens.RowPaddingVerticalDip),
                categoryWidthPx:=CommandPaletteTokens.CategoryWidthDip * safeProfile.DpiScale * content,
                shortcutWidthPx:=CommandPaletteTokens.ShortcutWidthDip * safeProfile.DpiScale * content,
                cornerRadiusPx:=safeProfile.ChromeDipToPx(CommandPaletteTokens.CornerRadiusDip),
                searchRadiusPx:=safeProfile.ChromeDipToPx(CommandPaletteTokens.SearchRadiusDip),
                rowRadiusPx:=safeProfile.ChromeDipToPx(CommandPaletteTokens.RowRadiusDip),
                strokePx:=safeProfile.ChromeDipToPx(CommandPaletteTokens.StrokeDip),
                focusStrokePx:=safeProfile.ChromeDipToPx(CommandPaletteTokens.FocusStrokeDip),
                showHeader:=showHeader,
                showMetadata:=showMetadata,
                showCategory:=showCategory,
                showShortcut:=showShortcut,
                showDescription:=showDescription)
        End Function

        Friend Function ResolveHeaderRect(bounds As SKRect) As SKRect
            If Not ShowHeader Then Return SKRect.Empty
            Return New SKRect(bounds.Left + PaddingPx, bounds.Top + PaddingPx, bounds.Right - PaddingPx, bounds.Top + PaddingPx + HeaderHeightPx)
        End Function

        Friend Function ResolveSearchRect(bounds As SKRect) As SKRect
            Dim top As Single = bounds.Top + PaddingPx + HeaderHeightPx + HeaderSearchGapPx
            Return New SKRect(bounds.Left + PaddingPx, top, bounds.Right - PaddingPx, top + SearchHeightPx)
        End Function

        Friend Function ResolveResultsRect(bounds As SKRect) As SKRect
            Dim search As SKRect = ResolveSearchRect(bounds)
            Return New SKRect(bounds.Left + PaddingPx, search.Bottom + SearchResultsGapPx, bounds.Right - PaddingPx, bounds.Bottom - PaddingPx)
        End Function

        Private Shared Function CreateFallbackProfile() As MASResponsiveLayoutProfile
            Return MASResponsiveLayoutResolver.FromLogicalSize(MASSizeLayoutIntegrationContext.Empty, SKSize.Empty, MASSize.Default, Thresholds)
        End Function

        Private Shared Function ClampScale(value As Single, minimum As Single, maximum As Single) As Single
            If Single.IsNaN(value) OrElse Single.IsInfinity(value) OrElse value <= 0.0F Then Return 1.0F
            Return Math.Min(maximum, Math.Max(minimum, value))
        End Function
    End Class

End Namespace
