Option Strict On
Option Explicit On

Imports System
Imports Nexamas.UI.Application
Imports Nexamas.UI.Controls
Imports Nexamas.UI.Layout

Namespace Nexamas.UI.Presentation

    ''' <summary>
    ''' Official Nexamas UI presentation-page recipe builder. It is not a new renderer
    ''' and not a second controls API; it applies the product page contract to the
    ''' existing MASApplication LayoutPage gateway so pages share one header/body/footer
    ''' language while still supplying their own content controls.
    ''' </summary>
    Friend NotInheritable Class MASPresentationPageBuilder
        Private ReadOnly _page As MASApplicationLayoutPageBuilder

        Friend Sub New(page As MASApplicationLayoutPageBuilder)
            If page Is Nothing Then Throw New ArgumentNullException(NameOf(page))
            _page = page
        End Sub

        ''' <summary>
        ''' Adds the official page header: MASTitle title with divider, then an optional
        ''' description label with breathing room. Pages must not recreate this with a
        ''' compressed Section(title, description) call.
        ''' </summary>
        Public Function Header(title As MASTitle,
                               Optional description As MASLabel = Nothing) As MASPresentationPageBuilder
            If title IsNot Nothing Then
                _page.FullWidth(title, MASPresentationPageMetrics.HeaderTitleSize())
            End If

            If description IsNot Nothing Then
                _page.FullWidth(description, MASPresentationPageMetrics.HeaderDescriptionSize())
            End If

            Return Me
        End Function

        ''' <summary>
        ''' Adds a body-section heading and optional instruction/description label below
        ''' the page header using the same official spacing policy as other product pages.
        ''' </summary>
        Public Function SectionIntro(heading As MASLabel,
                                     Optional description As MASLabel = Nothing) As MASPresentationPageBuilder
            If heading IsNot Nothing Then
                _page.FullWidth(heading, MASPresentationPageMetrics.SectionHeadingSize())
            End If

            If description IsNot Nothing Then
                _page.FullWidth(description, MASPresentationPageMetrics.SectionDescriptionSize())
            End If

            Return Me
        End Function

        ''' <summary>
        ''' Adds a full-width body control through the underlying official LayoutPage gateway.
        ''' </summary>
        Public Function FullWidth(control As MASControlBase,
                                  Optional sizeIntent As MASSize = Nothing) As MASPresentationPageBuilder
            If control IsNot Nothing Then
                _page.FullWidth(control, If(sizeIntent, MASPresentationPageMetrics.BodyFullWidthSize()))
            End If

            Return Me
        End Function

        ''' <summary>
        ''' Adds a full-width body control while preserving the control's own MASSize
        ''' intent as the retained source of truth. MAS-owned dashboard pages use this
        ''' for read-model driven surfaces that can collapse or cap their visible rows.
        ''' </summary>
        Friend Function FullWidthUsingControlSize(control As MASControlBase) As MASPresentationPageBuilder
            If control IsNot Nothing Then
                _page.FullWidthUsingControlSize(control)
            End If

            Return Me
        End Function

        ''' <summary>
        ''' Adds a semantic full-width body surface. Use this for list/tree/grid/preview
        ''' bodies instead of carrying local OffsetHeight numbers in product pages.
        ''' </summary>
        Public Function Surface(control As MASControlBase,
                                kind As MASPresentationSurfaceKind) As MASPresentationPageBuilder
            If control IsNot Nothing Then
                _page.FullWidth(control, MASPresentationPageMetrics.BodySurfaceSize(kind))
            End If

            Return Me
        End Function

        ''' <summary>
        ''' Adds the official single-list presentation slot.
        ''' </summary>
        Public Function SelectionListSurface(control As MASControlBase) As MASPresentationPageBuilder
            Return Surface(control, MASPresentationSurfaceKind.SelectionList)
        End Function

        ''' <summary>
        ''' Adds the official paired-collection presentation slot.
        ''' </summary>
        Public Function CollectionPairSurface(control As MASControlBase) As MASPresentationPageBuilder
            Return Surface(control, MASPresentationSurfaceKind.CollectionPair)
        End Function

        ''' <summary>
        ''' Adds the official tree presentation slot.
        ''' </summary>
        Public Function TreeSurface(control As MASControlBase) As MASPresentationPageBuilder
            Return Surface(control, MASPresentationSurfaceKind.Tree)
        End Function

        ''' <summary>
        ''' Adds the official tile-gallery presentation slot.
        ''' </summary>
        Public Function TileGallerySurface(control As MASControlBase) As MASPresentationPageBuilder
            Return Surface(control, MASPresentationSurfaceKind.TileGallery)
        End Function

        ''' <summary>
        ''' Adds the official data-grid presentation slot.
        ''' </summary>
        Public Function DataGridSurface(control As MASControlBase) As MASPresentationPageBuilder
            Return Surface(control, MASPresentationSurfaceKind.DataGrid)
        End Function
        ''' <summary>
        ''' Adds an official narrative/surface row: explanatory MAS content in the left pane
        ''' and a semantic Presentation surface in the right pane. This is the correct route
        ''' for product/demo pages that need text beside a list/tree/grid without local widths
        ''' or ad-hoc showcase helpers.
        ''' </summary>
        Public Function NarrativeSurface(narrative As MASControlBase,
                                         surface As MASControlBase,
                                         kind As MASPresentationSurfaceKind) As MASPresentationPageBuilder
            Return NarrativeSurface(narrative, Nothing, surface, kind)
        End Function

        ''' <summary>
        ''' Adds an official narrative/surface row with an optional secondary proof/notes label
        ''' stacked under the primary narrative text.
        ''' </summary>
        Public Function NarrativeSurface(narrative As MASControlBase,
                                         secondaryNarrative As MASControlBase,
                                         surface As MASControlBase,
                                         kind As MASPresentationSurfaceKind) As MASPresentationPageBuilder
            If narrative Is Nothing AndAlso secondaryNarrative Is Nothing Then
                Return Me.Surface(surface, kind)
            End If

            If surface Is Nothing Then
                If narrative IsNot Nothing Then FullWidth(narrative, MASPresentationPageMetrics.NarrativePaneSize())
                If secondaryNarrative IsNot Nothing Then FullWidth(secondaryNarrative, MASPresentationPageMetrics.NarrativePaneSize())
                Return Me
            End If

            Dim split As MASApplicationSplitPaneLayoutBuilder = _page.SplitPane()
            split.Gap(MASLayoutSpacing.Spacious)
            If narrative IsNot Nothing Then split.AddNarrative(narrative, MASPresentationPageMetrics.NarrativePaneSize())
            If secondaryNarrative IsNot Nothing Then split.AddNarrative(secondaryNarrative, MASPresentationPageMetrics.NarrativePaneSize())
            split.AddSurface(surface, MASPresentationPageMetrics.BodySurfaceSize(kind))
            Return Me
        End Function

        Public Function NarrativeSelectionListSurface(narrative As MASControlBase,
                                                      secondaryNarrative As MASControlBase,
                                                      surface As MASControlBase) As MASPresentationPageBuilder
            Return NarrativeSurface(narrative, secondaryNarrative, surface, MASPresentationSurfaceKind.SelectionList)
        End Function

        Public Function NarrativeCollectionPairSurface(narrative As MASControlBase,
                                                       secondaryNarrative As MASControlBase,
                                                       surface As MASControlBase) As MASPresentationPageBuilder
            Return NarrativeSurface(narrative, secondaryNarrative, surface, MASPresentationSurfaceKind.CollectionPair)
        End Function

        Public Function NarrativeCollectionPairSurface(narrative As MASControlBase,
                                                       secondaryNarrative As MASControlBase,
                                                       tertiaryNarrative As MASControlBase,
                                                       firstSurface As MASControlBase,
                                                       secondSurface As MASControlBase) As MASPresentationPageBuilder
            Return NarrativeSurfaceGrid(narrative,
                                        secondaryNarrative,
                                        tertiaryNarrative,
                                        MASPresentationSurfaceKind.CollectionPair,
                                        2,
                                        firstSurface,
                                        secondSurface)
        End Function

        Public Function NarrativeDataGridSurface(narrative As MASControlBase,
                                                 secondaryNarrative As MASControlBase,
                                                 surfaceHeader As MASControlBase,
                                                 gridSurface As MASControlBase) As MASPresentationPageBuilder
            Return NarrativeSurfaceStack(narrative,
                                         secondaryNarrative,
                                         MASPresentationSurfaceKind.DataGrid,
                                         surfaceHeader,
                                         gridSurface)
        End Function

        ''' <summary>
        ''' Adds an official text-left/default-control-right inspection surface. Use this for
        ''' focused controls such as segmented controls, tabs, and selector items where the
        ''' page must keep narrative text out of the header but must not promote those controls
        ''' into list/tree/data surfaces or introduce demo-local widths.
        ''' </summary>
        Public Function NarrativeControlInspectionSurface(narrative As MASControlBase,
                                                          secondaryNarrative As MASControlBase,
                                                          tertiaryNarrative As MASControlBase,
                                                          ParamArray controls() As MASControlBase) As MASPresentationPageBuilder
            Dim split As MASApplicationSplitPaneLayoutBuilder = BeginNarrativeControlInspectionSplit(narrative, secondaryNarrative, tertiaryNarrative)
            If controls IsNot Nothing Then
                For Each control As MASControlBase In controls
                    If control IsNot Nothing Then
                        split.AddSurface(control, MASSize.[Default])
                    End If
                Next
            End If
            Return Me
        End Function

        ''' <summary>
        ''' Starts an internal narrative/control split for MAS-owned Application pages that
        ''' need Application-specific surface sizing while still taking the narrative pane
        ''' size intent from Presentation. Application code must use this gateway instead
        ''' of calling MASPresentationPageMetrics directly.
        ''' </summary>
        Friend Function BeginNarrativeControlInspectionSplit(narrative As MASControlBase,
                                                             secondaryNarrative As MASControlBase,
                                                             tertiaryNarrative As MASControlBase) As MASApplicationSplitPaneLayoutBuilder
            Return CreateNarrativeSplit(narrative, secondaryNarrative, tertiaryNarrative)
        End Function

        Private Function NarrativeSurfaceGrid(narrative As MASControlBase,
                                              secondaryNarrative As MASControlBase,
                                              tertiaryNarrative As MASControlBase,
                                              kind As MASPresentationSurfaceKind,
                                              columns As Integer,
                                              ParamArray surfaces() As MASControlBase) As MASPresentationPageBuilder
            Dim split As MASApplicationSplitPaneLayoutBuilder = CreateNarrativeSplit(narrative, secondaryNarrative, tertiaryNarrative)
            split.AddSurfaceGrid(Math.Max(1, columns), ToApplicationSurfaceKind(kind), surfaces)
            Return Me
        End Function

        Private Function NarrativeSurfaceStack(narrative As MASControlBase,
                                               secondaryNarrative As MASControlBase,
                                               kind As MASPresentationSurfaceKind,
                                               ParamArray surfaces() As MASControlBase) As MASPresentationPageBuilder
            Dim split As MASApplicationSplitPaneLayoutBuilder = CreateNarrativeSplit(narrative, secondaryNarrative, Nothing)
            If surfaces IsNot Nothing Then
                Dim sizeIntent As MASSize = MASPresentationPageMetrics.BodySurfaceSize(kind)
                Dim index As Integer = 0
                For Each surfaceControl As MASControlBase In surfaces
                    If surfaceControl IsNot Nothing Then
                        If index = 0 Then
                            split.AddSurface(surfaceControl, MASPresentationPageMetrics.SurfaceHeaderSize())
                        Else
                            split.AddSurface(surfaceControl, sizeIntent)
                        End If
                    End If
                    index += 1
                Next
            End If
            Return Me
        End Function

        Private Function CreateNarrativeSplit(narrative As MASControlBase,
                                              secondaryNarrative As MASControlBase,
                                              tertiaryNarrative As MASControlBase) As MASApplicationSplitPaneLayoutBuilder
            Dim split As MASApplicationSplitPaneLayoutBuilder = _page.SplitPane()
            split.Gap(MASLayoutSpacing.Spacious)
            If narrative IsNot Nothing Then split.AddNarrative(narrative, MASPresentationPageMetrics.NarrativePaneSize())
            If secondaryNarrative IsNot Nothing Then split.AddNarrative(secondaryNarrative, MASPresentationPageMetrics.NarrativePaneSize())
            If tertiaryNarrative IsNot Nothing Then split.AddNarrative(tertiaryNarrative, MASPresentationPageMetrics.NarrativePaneSize())
            Return split
        End Function

        ''' <summary>
        ''' Adds a body grid with semantic MASLayout spacing. The returned grid builder is
        ''' still the official MASApplication grid builder, so consumers do not receive a
        ''' parallel layout engine.
        ''' </summary>
        Private Shared Function ToApplicationSurfaceKind(kind As MASPresentationSurfaceKind) As MASApplicationControlSurfaceSizeKind
            Select Case kind
                Case MASPresentationSurfaceKind.SelectionList
                    Return MASApplicationControlSurfaceSizeKind.SelectionList
                Case MASPresentationSurfaceKind.CollectionPair
                    Return MASApplicationControlSurfaceSizeKind.CollectionPair
                Case MASPresentationSurfaceKind.Tree
                    Return MASApplicationControlSurfaceSizeKind.TreeSurface
                Case MASPresentationSurfaceKind.TileGallery
                    Return MASApplicationControlSurfaceSizeKind.TileGallery
                Case MASPresentationSurfaceKind.DataGrid
                    Return MASApplicationControlSurfaceSizeKind.DataGrid
                Case MASPresentationSurfaceKind.Document
                    Return MASApplicationControlSurfaceSizeKind.Document
                Case MASPresentationSurfaceKind.Inspector
                    Return MASApplicationControlSurfaceSizeKind.Inspector
                Case Else
                    Return MASApplicationControlSurfaceSizeKind.Standard
            End Select
        End Function

        Public Function Grid(columns As Integer,
                             Optional gap As MASLayoutSpacing = MASLayoutSpacing.Large) As MASApplicationLayoutGridBuilder
            Dim gridBuilder As MASApplicationLayoutGridBuilder = _page.Grid(columns)
            gridBuilder.Gap(gap)
            Return gridBuilder
        End Function

        ''' <summary>
        ''' Adds a footer action group at the bottom of the page. Use this for page commands
        ''' instead of placing buttons as arbitrary body rows.
        ''' </summary>
        Public Function Actions(configure As Action(Of MASApplicationActionGroupLayoutBuilder)) As MASPresentationPageBuilder
            If configure Is Nothing Then Throw New ArgumentNullException(NameOf(configure))
            _page.ActionGroup(configure)
            Return Me
        End Function

        ''' <summary>
        ''' Adds one full-width footer action for simple pages that expose a single primary command.
        ''' </summary>
        Public Function FooterAction(control As MASControlBase,
                                     Optional sizeIntent As MASSize = Nothing) As MASPresentationPageBuilder
            If control IsNot Nothing Then
                _page.FullWidth(control, If(sizeIntent, MASPresentationPageMetrics.FooterActionSize()))
            End If

            Return Me
        End Function
    End Class

End Namespace
