Option Strict On
Option Explicit On

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

Namespace Nexamas.UI.Components

    Friend Enum MASTransferListLayoutKind
        TwoPane = 0
        Stacked = 1
        Minimal = 2
    End Enum

    ''' <summary>
    ''' Render-only responsive layout facts for MASTransferList. It converts the
    ''' official runtime size profile and available bounds into two-pane or stacked
    ''' visual geometry without introducing a parallel size system.
    ''' </summary>
    Friend NotInheritable Class MASTransferListLayoutPlan
        Friend Shared ReadOnly Thresholds As New MASResponsiveLayoutThresholds(
            fullWidthDip:=TransferListTokens.PreferredWidthDip,
            fullHeightDip:=TransferListTokens.PreferredHeightDip,
            denseWidthDip:=620.0F,
            denseHeightDip:=300.0F,
            compactWidthDip:=430.0F,
            compactHeightDip:=260.0F,
            minimalWidthDip:=240.0F,
            minimalHeightDip:=190.0F)

        Friend ReadOnly Property ResponsiveProfile As MASResponsiveLayoutProfile
        Friend ReadOnly Property Mode As MASResponsiveLayoutMode
        Friend ReadOnly Property Kind As MASTransferListLayoutKind
        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 PanelPaddingPx As Single
        Friend ReadOnly Property GapPx As Single
        Friend ReadOnly Property RailWidthPx As Single
        Friend ReadOnly Property RailHeightPx As Single
        Friend ReadOnly Property PanelRadiusPx As Single
        Friend ReadOnly Property RowHeightPx As Single
        Friend ReadOnly Property RowGapPx As Single
        Friend ReadOnly Property SearchHeightPx As Single
        Friend ReadOnly Property ButtonHeightPx As Single
        Friend ReadOnly Property ButtonGapPx As Single
        Friend ReadOnly Property ButtonRadiusPx As Single
        Friend ReadOnly Property MaxVisibleRows As Integer
        Friend ReadOnly Property ShowTitle As Boolean
        Friend ReadOnly Property ShowSearch As Boolean
        Friend ReadOnly Property ShowPanelCounts As Boolean
        Friend ReadOnly Property IsStacked As Boolean

        Private Sub New(profile As MASResponsiveLayoutProfile,
                        kind As MASTransferListLayoutKind,
                        contentInsetPx As Single,
                        headerHeightPx As Single,
                        headerGapPx As Single,
                        panelPaddingPx As Single,
                        gapPx As Single,
                        railWidthPx As Single,
                        railHeightPx As Single,
                        panelRadiusPx As Single,
                        rowHeightPx As Single,
                        rowGapPx As Single,
                        searchHeightPx As Single,
                        buttonHeightPx As Single,
                        buttonGapPx As Single,
                        buttonRadiusPx As Single,
                        maxVisibleRows As Integer,
                        showTitle As Boolean,
                        showSearch As Boolean,
                        showPanelCounts 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.Kind = kind
            Me.Dpi = Math.Max(0.64F, PositiveOrDefault(safeProfile.DpiScale, 1.0F))
            Me.ContentInsetPx = PositiveOrZero(contentInsetPx)
            Me.HeaderHeightPx = PositiveOrZero(headerHeightPx)
            Me.HeaderGapPx = PositiveOrZero(headerGapPx)
            Me.PanelPaddingPx = PositiveOrZero(panelPaddingPx)
            Me.GapPx = PositiveOrZero(gapPx)
            Me.RailWidthPx = PositiveOrZero(railWidthPx)
            Me.RailHeightPx = PositiveOrZero(railHeightPx)
            Me.PanelRadiusPx = PositiveOrZero(panelRadiusPx)
            Me.RowHeightPx = Math.Max(18.0F, PositiveOrDefault(rowHeightPx, 18.0F))
            Me.RowGapPx = PositiveOrZero(rowGapPx)
            Me.SearchHeightPx = PositiveOrZero(searchHeightPx)
            Me.ButtonHeightPx = Math.Max(20.0F, PositiveOrDefault(buttonHeightPx, 20.0F))
            Me.ButtonGapPx = PositiveOrZero(buttonGapPx)
            Me.ButtonRadiusPx = PositiveOrZero(buttonRadiusPx)
            Me.MaxVisibleRows = Math.Max(1, maxVisibleRows)
            Me.ShowTitle = showTitle
            Me.ShowSearch = showSearch
            Me.ShowPanelCounts = showPanelCounts
            Me.IsStacked = kind <> MASTransferListLayoutKind.TwoPane
        End Sub

        Friend Shared Function Create(profile As MASResponsiveLayoutProfile) As MASTransferListLayoutPlan
            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 kind As MASTransferListLayoutKind
            Select Case safeProfile.Mode
                Case MASResponsiveLayoutMode.Full, MASResponsiveLayoutMode.Dense
                    kind = MASTransferListLayoutKind.TwoPane
                Case MASResponsiveLayoutMode.Compact
                    kind = MASTransferListLayoutKind.Stacked
                Case Else
                    kind = MASTransferListLayoutKind.Minimal
            End Select

            Dim showTitle As Boolean = safeProfile.Mode <> MASResponsiveLayoutMode.Collapsed
            Dim showSearch As Boolean = safeProfile.Mode <> MASResponsiveLayoutMode.Minimal AndAlso safeProfile.Mode <> MASResponsiveLayoutMode.Collapsed
            Dim showCounts As Boolean = safeProfile.Mode = MASResponsiveLayoutMode.Full OrElse safeProfile.Mode = MASResponsiveLayoutMode.Dense OrElse safeProfile.Mode = MASResponsiveLayoutMode.Compact

            Dim maxRows As Integer
            Select Case safeProfile.Mode
                Case MASResponsiveLayoutMode.Full
                    maxRows = TransferListTokens.MaxVisibleRows
                Case MASResponsiveLayoutMode.Dense
                    maxRows = Math.Min(7, TransferListTokens.MaxVisibleRows)
                Case MASResponsiveLayoutMode.Compact
                    maxRows = 5
                Case Else
                    maxRows = 3
            End Select

            Return New MASTransferListLayoutPlan(
                profile:=safeProfile,
                kind:=kind,
                contentInsetPx:=TransferListTokens.PaddingDip * chromeDpi,
                headerHeightPx:=If(showTitle, TransferListTokens.HeaderHeightDip * chromeDpi, 0.0F),
                headerGapPx:=If(showTitle, TransferListTokens.GapDip * gapDpi, 0.0F),
                panelPaddingPx:=TransferListTokens.PanelPaddingDip * chromeDpi,
                gapPx:=TransferListTokens.GapDip * gapDpi,
                railWidthPx:=If(kind = MASTransferListLayoutKind.TwoPane, TransferListTokens.CenterRailWidthDip * chromeDpi, 0.0F),
                railHeightPx:=If(kind = MASTransferListLayoutKind.TwoPane, 0.0F, 42.0F * chromeDpi),
                panelRadiusPx:=TransferListTokens.PanelRadiusDip * chromeDpi,
                rowHeightPx:=If(showSearch, TransferListTokens.RowHeightDip, 30.0F) * contentDpi,
                rowGapPx:=TransferListTokens.RowGapDip * gapDpi,
                searchHeightPx:=If(showSearch, 26.0F * chromeDpi, 0.0F),
                buttonHeightPx:=TransferListTokens.ButtonHeightDip * chromeDpi,
                buttonGapPx:=TransferListTokens.ButtonGapDip * gapDpi,
                buttonRadiusPx:=TransferListTokens.ButtonRadiusDip * chromeDpi,
                maxVisibleRows:=maxRows,
                showTitle:=showTitle,
                showSearch:=showSearch,
                showPanelCounts:=showCounts)
        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
