Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports Nexamas.UI.Controls
Imports Nexamas.UI.Layout

Namespace Nexamas.UI.Composition

    ' <summary>
    ' Shared MASPage template helpers, padding policies, and wrapping utilities.
    ' </summary>
    Partial Friend NotInheritable Class MASPage

        ''' <summary>
        ''' Internal template builder used by the section-based Page templates.
        ''' It centralizes title/description/actions chrome, padding policy, max width, and optional scroll wrapping
        ''' so public templates remain semantic recipes instead of separate layout runtimes.
        ''' </summary>
        Private Shared Function BuildSectionTemplatePage(Of TSection As Class)(sections As IEnumerable(Of TSection),
                                                                               sectionToItem As Func(Of TSection, MASLayoutItem),
                                                                               title As MASControlBase,
                                                                               description As MASControlBase,
                                                                               actions As IMASLayoutNode,
                                                                               spacing As Single,
                                                                               padding As MASLayoutThickness,
                                                                               titleHeight As MASSizePolicy,
                                                                               descriptionHeight As MASSizePolicy,
                                                                               actionsWidth As MASSizePolicy,
                                                                               actionsHeight As MASSizePolicy,
                                                                               maxContentWidth As Single,
                                                                               scrollEnabled As Boolean,
                                                                               scrollKey As String,
                                                                               useDefaultVisualPolish As Boolean,
                                                                               paddingResolver As Func(Of MASLayoutThickness, Boolean, MASLayoutThickness)) As IMASLayoutNode

            If sectionToItem Is Nothing Then Throw New ArgumentNullException(NameOf(sectionToItem))
            If paddingResolver Is Nothing Then Throw New ArgumentNullException(NameOf(paddingResolver))

            Dim pageItems As New List(Of MASLayoutItem)()

            AddTemplateHeaderItems(
                items:=pageItems,
                title:=title,
                description:=description,
                titleHeight:=titleHeight,
                descriptionHeight:=descriptionHeight,
                useDefaultVisualPolish:=useDefaultVisualPolish)

            If sections IsNot Nothing Then
                For Each section As TSection In sections
                    If section IsNot Nothing Then
                        Dim sectionItem As MASLayoutItem = sectionToItem(section)
                        If sectionItem IsNot Nothing Then
                            pageItems.Add(sectionItem)
                        End If
                    End If
                Next
            End If

            AddTemplateActionsItem(
                items:=pageItems,
                actions:=actions,
                actionsWidth:=actionsWidth,
                actionsHeight:=actionsHeight,
                useDefaultVisualPolish:=useDefaultVisualPolish)

            Dim pageNode As IMASLayoutNode =
                MASComposition.Vertical(
                    children:=pageItems.ToArray(),
                    spacing:=SafeSpacing(spacing),
                    padding:=paddingResolver(padding, useDefaultVisualPolish),
                    alignment:=MASLayoutAlignment.Stretch)

            Return WrapScrollableOrMaxContentWidth(
                node:=pageNode,
                maxContentWidth:=maxContentWidth,
                scrollEnabled:=scrollEnabled,
                scrollKey:=scrollKey)
        End Function

        Private Shared Sub AddTemplateHeaderItems(items As IList(Of MASLayoutItem),
                                                  title As MASControlBase,
                                                  description As MASControlBase,
                                                  titleHeight As MASSizePolicy,
                                                  descriptionHeight As MASSizePolicy,
                                                  useDefaultVisualPolish As Boolean)
            If items Is Nothing Then Throw New ArgumentNullException(NameOf(items))

            If title IsNot Nothing Then
                items.Add(
                    MASComposition.Item(
                        control:=title,
                        width:=MASSizePolicy.Fill(1.0F),
                        height:=If(titleHeight, MASSizePolicy.Auto()),
                        alignment:=MASLayoutAlignment.Stretch,
                        margin:=ResolveFormTitleMargin(useDefaultVisualPolish))
                )
            End If

            If description IsNot Nothing Then
                items.Add(
                    MASComposition.Item(
                        control:=description,
                        width:=MASSizePolicy.Fill(1.0F),
                        height:=If(descriptionHeight, MASSizePolicy.Auto()),
                        alignment:=MASLayoutAlignment.Stretch,
                        margin:=ResolveFormDescriptionMargin(useDefaultVisualPolish))
                )
            End If
        End Sub

        Private Shared Sub AddTemplateActionsItem(items As IList(Of MASLayoutItem),
                                                  actions As IMASLayoutNode,
                                                  actionsWidth As MASSizePolicy,
                                                  actionsHeight As MASSizePolicy,
                                                  useDefaultVisualPolish As Boolean)
            If items Is Nothing Then Throw New ArgumentNullException(NameOf(items))
            If actions Is Nothing Then Return

            items.Add(
                MASComposition.NodeItem(
                    node:=actions,
                    width:=If(actionsWidth, MASSizePolicy.Auto()),
                    height:=If(actionsHeight, MASSizePolicy.Auto()),
                    alignment:=MASLayoutAlignment.End,
                    margin:=ResolveFormActionsMargin(useDefaultVisualPolish))
            )
        End Sub

        Private Shared Function WrapScrollableOrMaxContentWidth(node As IMASLayoutNode,
                                                                maxContentWidth As Single,
                                                                scrollEnabled As Boolean,
                                                                scrollKey As String) As IMASLayoutNode
            If node Is Nothing Then Return Nothing

            If scrollEnabled Then
                Return New MASVerticalScrollLayoutNode(
                    content:=node,
                    scrollKey:=If(scrollKey, String.Empty),
                    maxContentWidth:=maxContentWidth)
            End If

            Return WrapMaxContentWidth(node, maxContentWidth)
        End Function

        Private Shared Function ResolveWizardPagePadding(value As MASLayoutThickness, useDefaultVisualPolish As Boolean) As MASLayoutThickness
            If useDefaultVisualPolish AndAlso IsEmptyThickness(value) Then
                Return MASCompositionPageSizeTokens.WizardPagePadding()
            End If

            Return value
        End Function

        Private Shared Function ResolveWizardProgressMargin(useDefaultVisualPolish As Boolean) As MASLayoutThickness
            If Not useDefaultVisualPolish Then Return MASLayoutThickness.None()
            Return MASCompositionPageSizeTokens.WizardProgressMargin()
        End Function

        Private Shared Function ResolveDetailsPagePadding(value As MASLayoutThickness, useDefaultVisualPolish As Boolean) As MASLayoutThickness
            If useDefaultVisualPolish AndAlso IsEmptyThickness(value) Then
                Return MASCompositionPageSizeTokens.DetailsPagePadding()
            End If

            Return value
        End Function

        Private Shared Function ResolveEmptyStatePadding(value As MASLayoutThickness, useDefaultVisualPolish As Boolean) As MASLayoutThickness
            If useDefaultVisualPolish AndAlso IsEmptyThickness(value) Then
                Return MASCompositionPageSizeTokens.EmptyStatePadding()
            End If

            Return value
        End Function

        Private Shared Function ResolveEmptyIllustrationMargin(useDefaultVisualPolish As Boolean) As MASLayoutThickness
            If Not useDefaultVisualPolish Then Return MASLayoutThickness.None()
            Return MASCompositionPageSizeTokens.EmptyIllustrationMargin()
        End Function

        Private Shared Function ResolveEmptyTitleMargin(useDefaultVisualPolish As Boolean) As MASLayoutThickness
            If Not useDefaultVisualPolish Then Return MASLayoutThickness.None()
            Return MASCompositionPageSizeTokens.EmptyTitleMargin()
        End Function

        Private Shared Function ResolveEmptyMessageMargin(useDefaultVisualPolish As Boolean) As MASLayoutThickness
            If Not useDefaultVisualPolish Then Return MASLayoutThickness.None()
            Return MASCompositionPageSizeTokens.EmptyMessageMargin()
        End Function

        Private Shared Function ResolveEmptyActionsMargin(useDefaultVisualPolish As Boolean) As MASLayoutThickness
            If Not useDefaultVisualPolish Then Return MASLayoutThickness.None()
            Return MASCompositionPageSizeTokens.EmptyActionsMargin()
        End Function

        Private Shared Function ResolveSettingsPagePadding(value As MASLayoutThickness, useDefaultVisualPolish As Boolean) As MASLayoutThickness
            If useDefaultVisualPolish AndAlso IsEmptyThickness(value) Then
                Return MASCompositionPageSizeTokens.SettingsPagePadding()
            End If

            Return value
        End Function

        Private Shared Function ResolveFormPadding(value As MASLayoutThickness, useDefaultVisualPolish As Boolean) As MASLayoutThickness
            If useDefaultVisualPolish AndAlso IsEmptyThickness(value) Then
                Return MASCompositionPageSizeTokens.FormPagePadding()
            End If

            Return value
        End Function

        Private Shared Function ResolveActionsPadding(value As MASLayoutThickness, useDefaultVisualPolish As Boolean) As MASLayoutThickness
            If useDefaultVisualPolish AndAlso IsEmptyThickness(value) Then
                Return MASCompositionPageSizeTokens.ActionsPadding()
            End If

            Return value
        End Function

        Private Shared Function ResolveFormTitleMargin(useDefaultVisualPolish As Boolean) As MASLayoutThickness
            If Not useDefaultVisualPolish Then Return MASLayoutThickness.None()
            Return MASCompositionPageSizeTokens.FormTitleMargin()
        End Function

        Private Shared Function ResolveFormDescriptionMargin(useDefaultVisualPolish As Boolean) As MASLayoutThickness
            If Not useDefaultVisualPolish Then Return MASLayoutThickness.None()
            Return MASCompositionPageSizeTokens.FormDescriptionMargin()
        End Function

        Private Shared Function ResolveFormActionsMargin(useDefaultVisualPolish As Boolean) As MASLayoutThickness
            If Not useDefaultVisualPolish Then Return MASLayoutThickness.None()
            Return MASCompositionPageSizeTokens.FormActionsMargin()
        End Function

        Private Shared Function IsEmptyThickness(value As MASLayoutThickness) As Boolean
            Return MASCompositionPageSizeTokens.IsEmptyThickness(value)
        End Function

        Private Shared Function SafeSpacing(value As Single) As Single
            Return MASCompositionPageSizeTokens.SafeSpacing(value)
        End Function

        Private Shared Function WrapMaxContentWidth(node As IMASLayoutNode,
                                            maxContentWidth As Single) As IMASLayoutNode
            If node Is Nothing Then Return Nothing

            If Not IsFinitePositive(maxContentWidth) Then
                Return node
            End If

            Return MASComposition.Vertical(
        spacing:=0.0F,
        padding:=MASLayoutThickness.None(),
        alignment:=MASLayoutAlignment.Center,
        children:=New MASLayoutItem() {
            MASComposition.NodeItem(
                node:=node,
                width:=MASSizePolicy.Fixed(maxContentWidth),
                height:=MASSizePolicy.Fill(1.0F),
                alignment:=MASLayoutAlignment.Center
            )
        }
    )
        End Function

        Private Shared Function IsFinitePositive(value As Single) As Boolean
            Return MASCompositionPageSizeTokens.IsFinitePositive(value)
        End Function

    End Class

End Namespace
