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 MASDataForm. Field editing/binding remains
    ''' outside the control; this plan owns only inner visual layout decisions.
    ''' </summary>
    Friend NotInheritable Class MASDataFormLayoutPlan
        Friend Shared ReadOnly Thresholds As New MASResponsiveLayoutThresholds(
            fullWidthDip:=DataFormTokens.PreferredWidthDip,
            fullHeightDip:=320.0F,
            denseWidthDip:=520.0F,
            denseHeightDip:=250.0F,
            compactWidthDip:=340.0F,
            compactHeightDip:=190.0F,
            minimalWidthDip:=230.0F,
            minimalHeightDip:=120.0F)

        Friend ReadOnly Property ResponsiveProfile As MASResponsiveLayoutProfile
        Friend ReadOnly Property Mode As MASResponsiveLayoutMode
        Friend ReadOnly Property Dpi As Single
        Friend ReadOnly Property PaddingHorizontalPx As Single
        Friend ReadOnly Property PaddingVerticalPx As Single
        Friend ReadOnly Property RadiusPx As Single
        Friend ReadOnly Property HeaderTitleHeightPx As Single
        Friend ReadOnly Property HeaderDescriptionHeightPx As Single
        Friend ReadOnly Property HeaderGapPx As Single
        Friend ReadOnly Property HeaderBottomGapPx As Single
        Friend ReadOnly Property SummaryHeightPx As Single
        Friend ReadOnly Property SummaryGapPx As Single
        Friend ReadOnly Property RowHeightPx As Single
        Friend ReadOnly Property RowGapPx As Single
        Friend ReadOnly Property RowRadiusPx As Single
        Friend ReadOnly Property RowPaddingHorizontalPx As Single
        Friend ReadOnly Property RowPaddingVerticalPx As Single
        Friend ReadOnly Property LabelColumnWidthPx As Single
        Friend ReadOnly Property HelperHeightPx As Single
        Friend ReadOnly Property ShowDescription As Boolean
        Friend ReadOnly Property ShowSummary As Boolean
        Friend ReadOnly Property ShowHelperText As Boolean
        Friend ReadOnly Property StackLabelAndValue As Boolean

        Private Sub New(profile As MASResponsiveLayoutProfile,
                        paddingHorizontalPx As Single,
                        paddingVerticalPx As Single,
                        radiusPx As Single,
                        headerTitleHeightPx As Single,
                        headerDescriptionHeightPx As Single,
                        headerGapPx As Single,
                        headerBottomGapPx As Single,
                        summaryHeightPx As Single,
                        summaryGapPx As Single,
                        rowHeightPx As Single,
                        rowGapPx As Single,
                        rowRadiusPx As Single,
                        rowPaddingHorizontalPx As Single,
                        rowPaddingVerticalPx As Single,
                        labelColumnWidthPx As Single,
                        helperHeightPx As Single,
                        showDescription As Boolean,
                        showSummary As Boolean,
                        showHelperText As Boolean,
                        stackLabelAndValue 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.PaddingHorizontalPx = PositiveOrZero(paddingHorizontalPx)
            Me.PaddingVerticalPx = PositiveOrZero(paddingVerticalPx)
            Me.RadiusPx = PositiveOrZero(radiusPx)
            Me.HeaderTitleHeightPx = PositiveOrZero(headerTitleHeightPx)
            Me.HeaderDescriptionHeightPx = PositiveOrZero(headerDescriptionHeightPx)
            Me.HeaderGapPx = PositiveOrZero(headerGapPx)
            Me.HeaderBottomGapPx = PositiveOrZero(headerBottomGapPx)
            Me.SummaryHeightPx = PositiveOrZero(summaryHeightPx)
            Me.SummaryGapPx = PositiveOrZero(summaryGapPx)
            Me.RowHeightPx = Math.Max(24.0F, PositiveOrDefault(rowHeightPx, 24.0F))
            Me.RowGapPx = PositiveOrZero(rowGapPx)
            Me.RowRadiusPx = PositiveOrZero(rowRadiusPx)
            Me.RowPaddingHorizontalPx = PositiveOrZero(rowPaddingHorizontalPx)
            Me.RowPaddingVerticalPx = PositiveOrZero(rowPaddingVerticalPx)
            Me.LabelColumnWidthPx = PositiveOrZero(labelColumnWidthPx)
            Me.HelperHeightPx = PositiveOrZero(helperHeightPx)
            Me.ShowDescription = showDescription
            Me.ShowSummary = showSummary
            Me.ShowHelperText = showHelperText
            Me.StackLabelAndValue = stackLabelAndValue
        End Sub

        Friend Shared Function Create(profile As MASResponsiveLayoutProfile,
                                      compactOverride As Boolean) As MASDataFormLayoutPlan
            Dim safeProfile As MASResponsiveLayoutProfile = If(profile, MASResponsiveLayoutResolver.FromLogicalSize(MASSizeLayoutIntegrationContext.Empty, SKSize.Empty, MASSize.Default, Thresholds))
            Dim dpi As Single = Math.Max(0.64F, 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 narrow As Boolean = safeProfile.Mode = MASResponsiveLayoutMode.Compact OrElse safeProfile.Mode = MASResponsiveLayoutMode.Minimal OrElse safeProfile.Mode = MASResponsiveLayoutMode.Collapsed OrElse safeProfile.AvailableSizeDip.Width < 420.0F
            Dim showDescription As Boolean = Not compactOverride AndAlso (safeProfile.Mode = MASResponsiveLayoutMode.Full OrElse safeProfile.Mode = MASResponsiveLayoutMode.Dense)
            Dim showSummary As Boolean = safeProfile.Mode <> MASResponsiveLayoutMode.Minimal AndAlso safeProfile.Mode <> MASResponsiveLayoutMode.Collapsed
            Dim showHelper As Boolean = Not compactOverride AndAlso safeProfile.Mode <> MASResponsiveLayoutMode.Minimal AndAlso safeProfile.Mode <> MASResponsiveLayoutMode.Collapsed
            Dim rowDip As Single = If(compactOverride OrElse safeProfile.Mode <> MASResponsiveLayoutMode.Full, DataFormTokens.DenseRowHeightDip, DataFormTokens.RowHeightDip)
            If narrow Then rowDip = Math.Max(rowDip, 58.0F)

            Return New MASDataFormLayoutPlan(
                profile:=safeProfile,
                paddingHorizontalPx:=DataFormTokens.PaddingHorizontalDip * gapDpi,
                paddingVerticalPx:=DataFormTokens.PaddingVerticalDip * gapDpi,
                radiusPx:=DataFormTokens.RadiusDip * chromeDpi,
                headerTitleHeightPx:=26.0F * chromeDpi,
                headerDescriptionHeightPx:=If(showDescription, 20.0F * contentDpi, 0.0F),
                headerGapPx:=DataFormTokens.HeaderGapDip * gapDpi,
                headerBottomGapPx:=DataFormTokens.HeaderBottomGapDip * gapDpi,
                summaryHeightPx:=If(showSummary, DataFormTokens.SummaryHeightDip * contentDpi, 0.0F),
                summaryGapPx:=If(showSummary, DataFormTokens.SummaryGapDip * gapDpi, 0.0F),
                rowHeightPx:=rowDip * contentDpi,
                rowGapPx:=DataFormTokens.RowGapDip * gapDpi,
                rowRadiusPx:=DataFormTokens.RowRadiusDip * chromeDpi,
                rowPaddingHorizontalPx:=DataFormTokens.RowPaddingHorizontalDip * gapDpi,
                rowPaddingVerticalPx:=DataFormTokens.RowPaddingVerticalDip * gapDpi,
                labelColumnWidthPx:=DataFormTokens.LabelColumnWidthDip * contentDpi,
                helperHeightPx:=If(showHelper, DataFormTokens.HelperHeightDip * contentDpi, 0.0F),
                showDescription:=showDescription,
                showSummary:=showSummary,
                showHelperText:=showHelper,
                stackLabelAndValue:=narrow)
        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
    End Class

End Namespace
