Option Strict On
Option Explicit On

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

Namespace Nexamas.UI.Components

    ''' <summary>
    ''' Render-only responsive layout facts for MASMasterDetailView. The public size
    ''' contract remains owned by MASSizeResolver; this plan translates the official
    ''' runtime size profile and current bounds into inner split/stacked drawing facts.
    ''' </summary>
    Friend NotInheritable Class MASMasterDetailViewLayoutPlan
        Friend Shared ReadOnly Thresholds As New MASResponsiveLayoutThresholds(
            fullWidthDip:=MasterDetailViewTokens.PreferredWidthDip,
            fullHeightDip:=MasterDetailViewTokens.PreferredHeightDip,
            denseWidthDip:=680.0F,
            denseHeightDip:=380.0F,
            compactWidthDip:=470.0F,
            compactHeightDip:=280.0F,
            minimalWidthDip:=250.0F,
            minimalHeightDip:=180.0F)

        Friend ReadOnly Property ResponsiveProfile As MASResponsiveLayoutProfile
        Friend ReadOnly Property Mode As MASResponsiveLayoutMode
        Friend ReadOnly Property Dpi As Single
        Friend ReadOnly Property ContentInsetPx As Single
        Friend ReadOnly Property HeaderHeightPx As Single
        Friend ReadOnly Property HeaderGapPx As Single
        Friend ReadOnly Property FooterHeightPx As Single
        Friend ReadOnly Property FooterGapPx As Single
        Friend ReadOnly Property PaneGapPx As Single
        Friend ReadOnly Property PanePaddingPx As Single
        Friend ReadOnly Property PaneRadiusPx As Single
        Friend ReadOnly Property DetailPaddingPx As Single
        Friend ReadOnly Property DetailGapPx As Single
        Friend ReadOnly Property DetailLineHeightPx As Single
        Friend ReadOnly Property DetailActionHeightPx As Single
        Friend ReadOnly Property ItemHeightPx As Single
        Friend ReadOnly Property ItemGapPx As Single
        Friend ReadOnly Property ItemPaddingPx As Single
        Friend ReadOnly Property ItemRadiusPx As Single
        Friend ReadOnly Property BadgeMinWidthPx As Single
        Friend ReadOnly Property BadgeMaxWidthPx As Single
        Friend ReadOnly Property MasterMinWidthPx As Single
        Friend ReadOnly Property MasterWidthRatio As Single
        Friend ReadOnly Property MasterMaxRatio As Single
        Friend ReadOnly Property SummaryWidthPx As Single
        Friend ReadOnly Property MaxVisibleItems As Integer
        Friend ReadOnly Property MaxDetailLines As Integer
        Friend ReadOnly Property ShowHeader As Boolean
        Friend ReadOnly Property ShowHeaderSummary As Boolean
        Friend ReadOnly Property ShowFooter As Boolean
        Friend ReadOnly Property ShowItemSubtitle As Boolean
        Friend ReadOnly Property ShowBadges As Boolean
        Friend ReadOnly Property ShowDetailEyebrow As Boolean
        Friend ReadOnly Property ShowDetailSubtitle As Boolean
        Friend ReadOnly Property ShowDetailActions As Boolean
        Friend ReadOnly Property IsStacked As Boolean

        Private Sub New(profile As MASResponsiveLayoutProfile,
                        contentInsetPx As Single,
                        headerHeightPx As Single,
                        headerGapPx As Single,
                        footerHeightPx As Single,
                        footerGapPx As Single,
                        paneGapPx As Single,
                        panePaddingPx As Single,
                        paneRadiusPx As Single,
                        detailPaddingPx As Single,
                        detailGapPx As Single,
                        detailLineHeightPx As Single,
                        detailActionHeightPx As Single,
                        itemHeightPx As Single,
                        itemGapPx As Single,
                        itemPaddingPx As Single,
                        itemRadiusPx As Single,
                        badgeMinWidthPx As Single,
                        badgeMaxWidthPx As Single,
                        masterMinWidthPx As Single,
                        masterWidthRatio As Single,
                        masterMaxRatio As Single,
                        summaryWidthPx As Single,
                        maxVisibleItems As Integer,
                        maxDetailLines As Integer,
                        showHeader As Boolean,
                        showHeaderSummary As Boolean,
                        showFooter As Boolean,
                        showItemSubtitle As Boolean,
                        showBadges As Boolean,
                        showDetailEyebrow As Boolean,
                        showDetailSubtitle As Boolean,
                        showDetailActions As Boolean,
                        isStacked As Boolean)
            Dim safeProfile As MASResponsiveLayoutProfile = If(profile, MASResponsiveLayoutResolver.FromLogicalSize(MASSizeLayoutIntegrationContext.Empty, SKSize.Empty, MASSize.Default, Thresholds))
            Me.ResponsiveProfile = safeProfile
            Me.Mode = safeProfile.Mode
            Me.Dpi = Math.Max(0.64F, PositiveOrDefault(safeProfile.DpiScale, 1.0F))
            Me.ContentInsetPx = PositiveOrZero(contentInsetPx)
            Me.HeaderHeightPx = PositiveOrZero(headerHeightPx)
            Me.HeaderGapPx = PositiveOrZero(headerGapPx)
            Me.FooterHeightPx = PositiveOrZero(footerHeightPx)
            Me.FooterGapPx = PositiveOrZero(footerGapPx)
            Me.PaneGapPx = PositiveOrZero(paneGapPx)
            Me.PanePaddingPx = PositiveOrZero(panePaddingPx)
            Me.PaneRadiusPx = PositiveOrZero(paneRadiusPx)
            Me.DetailPaddingPx = PositiveOrZero(detailPaddingPx)
            Me.DetailGapPx = PositiveOrZero(detailGapPx)
            Me.DetailLineHeightPx = Math.Max(10.0F, PositiveOrDefault(detailLineHeightPx, 10.0F))
            Me.DetailActionHeightPx = PositiveOrZero(detailActionHeightPx)
            Me.ItemHeightPx = Math.Max(24.0F, PositiveOrDefault(itemHeightPx, 24.0F))
            Me.ItemGapPx = PositiveOrZero(itemGapPx)
            Me.ItemPaddingPx = PositiveOrZero(itemPaddingPx)
            Me.ItemRadiusPx = PositiveOrZero(itemRadiusPx)
            Me.BadgeMinWidthPx = PositiveOrZero(badgeMinWidthPx)
            Me.BadgeMaxWidthPx = Math.Max(Me.BadgeMinWidthPx, PositiveOrZero(badgeMaxWidthPx))
            Me.MasterMinWidthPx = PositiveOrZero(masterMinWidthPx)
            Me.MasterWidthRatio = ClampRatio(masterWidthRatio, MasterDetailViewTokens.MasterWidthRatio)
            Me.MasterMaxRatio = ClampRatio(masterMaxRatio, MasterDetailViewTokens.MasterMaxRatio)
            Me.SummaryWidthPx = PositiveOrZero(summaryWidthPx)
            Me.MaxVisibleItems = Math.Max(1, maxVisibleItems)
            Me.MaxDetailLines = Math.Max(1, maxDetailLines)
            Me.ShowHeader = showHeader
            Me.ShowHeaderSummary = showHeaderSummary
            Me.ShowFooter = showFooter
            Me.ShowItemSubtitle = showItemSubtitle
            Me.ShowBadges = showBadges
            Me.ShowDetailEyebrow = showDetailEyebrow
            Me.ShowDetailSubtitle = showDetailSubtitle
            Me.ShowDetailActions = showDetailActions
            Me.IsStacked = isStacked
        End Sub

        Friend Shared Function Create(profile As MASResponsiveLayoutProfile) As MASMasterDetailViewLayoutPlan
            Dim safeProfile As MASResponsiveLayoutProfile = If(profile, MASResponsiveLayoutResolver.FromLogicalSize(MASSizeLayoutIntegrationContext.Empty, SKSize.Empty, MASSize.Default, Thresholds))
            Dim dpi As Single = safeProfile.DpiScale
            Dim chromeDpi As Single = Math.Max(0.64F, dpi * safeProfile.ChromeScale)
            Dim gapDpi As Single = Math.Max(0.64F, dpi * safeProfile.GapScale)
            Dim contentDpi As Single = Math.Max(0.64F, dpi * safeProfile.ContentScale)

            Dim showHeader As Boolean = safeProfile.Mode <> MASResponsiveLayoutMode.Collapsed
            Dim showFooter As Boolean = safeProfile.Mode = MASResponsiveLayoutMode.Full OrElse safeProfile.Mode = MASResponsiveLayoutMode.Dense
            Dim showSummary As Boolean = safeProfile.Mode = MASResponsiveLayoutMode.Full OrElse safeProfile.Mode = MASResponsiveLayoutMode.Dense
            Dim showItemSubtitle As Boolean = safeProfile.Mode <> MASResponsiveLayoutMode.Minimal AndAlso safeProfile.Mode <> MASResponsiveLayoutMode.Collapsed
            Dim showBadges As Boolean = safeProfile.Mode = MASResponsiveLayoutMode.Full OrElse safeProfile.Mode = MASResponsiveLayoutMode.Dense
            Dim showEyebrow As Boolean = safeProfile.Mode = MASResponsiveLayoutMode.Full OrElse safeProfile.Mode = MASResponsiveLayoutMode.Dense
            Dim showDetailSubtitle As Boolean = safeProfile.Mode <> MASResponsiveLayoutMode.Minimal AndAlso safeProfile.Mode <> MASResponsiveLayoutMode.Collapsed
            Dim showActions As Boolean = safeProfile.Mode = MASResponsiveLayoutMode.Full OrElse safeProfile.Mode = MASResponsiveLayoutMode.Dense
            Dim stacked As Boolean = safeProfile.Mode = MASResponsiveLayoutMode.Compact OrElse safeProfile.Mode = MASResponsiveLayoutMode.Minimal OrElse safeProfile.Mode = MASResponsiveLayoutMode.Collapsed

            Dim maxItems As Integer
            Dim maxLines As Integer
            Select Case safeProfile.Mode
                Case MASResponsiveLayoutMode.Full
                    maxItems = MasterDetailViewTokens.MaxVisibleItems
                    maxLines = MasterDetailViewTokens.MaxDetailLines
                Case MASResponsiveLayoutMode.Dense
                    maxItems = Math.Min(6, MasterDetailViewTokens.MaxVisibleItems)
                    maxLines = Math.Min(6, MasterDetailViewTokens.MaxDetailLines)
                Case MASResponsiveLayoutMode.Compact
                    maxItems = 4
                    maxLines = 4
                Case Else
                    maxItems = 3
                    maxLines = 3
            End Select

            Return New MASMasterDetailViewLayoutPlan(
                profile:=safeProfile,
                contentInsetPx:=MasterDetailViewTokens.PaddingDip * chromeDpi,
                headerHeightPx:=If(showHeader, MasterDetailViewTokens.HeaderHeightDip * chromeDpi, 0.0F),
                headerGapPx:=If(showHeader, MasterDetailViewTokens.PaneGapDip * gapDpi, 0.0F),
                footerHeightPx:=If(showFooter, MasterDetailViewTokens.FooterHeightDip * chromeDpi, 0.0F),
                footerGapPx:=If(showFooter, MasterDetailViewTokens.PaneGapDip * gapDpi, 0.0F),
                paneGapPx:=MasterDetailViewTokens.PaneGapDip * gapDpi,
                panePaddingPx:=MasterDetailViewTokens.PanePaddingDip * chromeDpi,
                paneRadiusPx:=MasterDetailViewTokens.PaneRadiusDip * chromeDpi,
                detailPaddingPx:=MasterDetailViewTokens.DetailPaddingDip * chromeDpi,
                detailGapPx:=MasterDetailViewTokens.DetailGapDip * gapDpi,
                detailLineHeightPx:=MasterDetailViewTokens.DetailLineHeightDip * contentDpi,
                detailActionHeightPx:=If(showActions, 34.0F * chromeDpi, 0.0F),
                itemHeightPx:=If(showItemSubtitle, MasterDetailViewTokens.ItemHeightDip, 48.0F) * contentDpi,
                itemGapPx:=MasterDetailViewTokens.ItemGapDip * gapDpi,
                itemPaddingPx:=MasterDetailViewTokens.ItemPaddingDip * chromeDpi,
                itemRadiusPx:=MasterDetailViewTokens.ItemRadiusDip * chromeDpi,
                badgeMinWidthPx:=MasterDetailViewTokens.BadgeMinWidthDip * chromeDpi,
                badgeMaxWidthPx:=MasterDetailViewTokens.BadgeMaxWidthDip * chromeDpi,
                masterMinWidthPx:=MasterDetailViewTokens.MasterMinWidthDip * chromeDpi,
                masterWidthRatio:=If(stacked, 1.0F, MasterDetailViewTokens.MasterWidthRatio),
                masterMaxRatio:=If(stacked, 1.0F, MasterDetailViewTokens.MasterMaxRatio),
                summaryWidthPx:=260.0F * chromeDpi,
                maxVisibleItems:=maxItems,
                maxDetailLines:=maxLines,
                showHeader:=showHeader,
                showHeaderSummary:=showSummary,
                showFooter:=showFooter,
                showItemSubtitle:=showItemSubtitle,
                showBadges:=showBadges,
                showDetailEyebrow:=showEyebrow,
                showDetailSubtitle:=showDetailSubtitle,
                showDetailActions:=showActions,
                isStacked:=stacked)
        End Function

        Private Shared Function PositiveOrDefault(value As Single, fallback As Single) As Single
            If Single.IsNaN(value) OrElse Single.IsInfinity(value) OrElse value <= 0.0F Then Return fallback
            Return value
        End Function

        Private Shared Function PositiveOrZero(value As Single) As Single
            If Single.IsNaN(value) OrElse Single.IsInfinity(value) OrElse value < 0.0F Then Return 0.0F
            Return value
        End Function

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

End Namespace
