Option Strict On
Option Explicit On

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

Namespace Nexamas.UI.Composition

    ''' <summary>
    ''' Host-scoped Page facade.
    ''' It creates MASPage recipes and can apply them through the owning MASCompositionHostRuntime.
    ''' </summary>
    <Global.System.ComponentModel.EditorBrowsable(Global.System.ComponentModel.EditorBrowsableState.Advanced)>
    Friend NotInheritable Class MASHostPageFacade

        Private ReadOnly _runtime As MASCompositionHostRuntime
        Private ReadOnly _textRecipeControls As New Dictionary(Of String, MASLabel)(StringComparer.Ordinal)
        Private ReadOnly _textRecipeUsedKeys As New HashSet(Of String)(StringComparer.Ordinal)
        Private _textRecipeBuildOrdinal As Integer
        Private _isInsideLayoutFactoryBuild As Boolean

        Friend Sub New(runtime As MASCompositionHostRuntime)
            If runtime Is Nothing Then Throw New ArgumentNullException(NameOf(runtime))
            _runtime = runtime
        End Sub

        Friend Function Vertical(Optional title As MASControlBase = Nothing,
                                 Optional description As MASControlBase = Nothing,
                                 Optional content As MASControlBase = Nothing,
                                 Optional actions As MASControlBase = Nothing,
                                 Optional spacing As Single = 12.0F,
                                 Optional padding As MASLayoutThickness = Nothing,
                                 Optional alignment As MASLayoutAlignment = MASLayoutAlignment.Stretch,
                                 Optional titleHeight As MASSizePolicy = Nothing,
                                 Optional descriptionHeight As MASSizePolicy = Nothing,
                                 Optional contentHeight As MASSizePolicy = Nothing,
                                 Optional actionsWidth As MASSizePolicy = Nothing,
                                 Optional actionsHeight As MASSizePolicy = Nothing,
                                 Optional maxContentWidth As Single = 0.0F) As IMASLayoutNode

            Return MASPage.Vertical(title, description, content, actions, spacing, padding, alignment, titleHeight, descriptionHeight, contentHeight, actionsWidth, actionsHeight, maxContentWidth)
        End Function

        Friend Function VerticalItems(children As IEnumerable(Of MASLayoutItem),
                                      Optional spacing As Single = 12.0F,
                                      Optional padding As MASLayoutThickness = Nothing,
                                      Optional alignment As MASLayoutAlignment = MASLayoutAlignment.Stretch,
                                      Optional maxContentWidth As Single = 0.0F) As IMASLayoutNode

            Return MASPage.Vertical(children, spacing, padding, alignment, maxContentWidth)
        End Function

        ''' <summary>
        ''' Host-scoped nested page recipe for title/description/content/action regions that are already layout nodes.
        ''' This is the Application-window gateway equivalent of MASPage.VerticalNodes and keeps external consumers
        ''' on window.Page instead of calling the static page recipe directly.
        ''' </summary>
        Friend Function VerticalNodes(Optional title As IMASLayoutNode = Nothing,
                                      Optional description As IMASLayoutNode = Nothing,
                                      Optional content As IMASLayoutNode = Nothing,
                                      Optional actions As IMASLayoutNode = Nothing,
                                      Optional spacing As Single = 12.0F,
                                      Optional padding As MASLayoutThickness = Nothing,
                                      Optional alignment As MASLayoutAlignment = MASLayoutAlignment.Stretch,
                                      Optional titleHeight As MASSizePolicy = Nothing,
                                      Optional descriptionHeight As MASSizePolicy = Nothing,
                                      Optional contentHeight As MASSizePolicy = Nothing,
                                      Optional actionsWidth As MASSizePolicy = Nothing,
                                      Optional actionsHeight As MASSizePolicy = Nothing,
                                      Optional maxContentWidth As Single = 0.0F) As IMASLayoutNode

            Return MASPage.VerticalNodes(title, description, content, actions, spacing, padding, alignment, titleHeight, descriptionHeight, contentHeight, actionsWidth, actionsHeight, maxContentWidth)
        End Function

        Friend Function Form(fields As IEnumerable(Of MASLayoutItem),
                             Optional title As MASControlBase = Nothing,
                             Optional description As MASControlBase = Nothing,
                             Optional submitArea As MASControlBase = Nothing,
                             Optional spacing As Single = 16.0F,
                             Optional padding As MASLayoutThickness = Nothing,
                             Optional titleHeight As MASSizePolicy = Nothing,
                             Optional descriptionHeight As MASSizePolicy = Nothing,
                             Optional submitAreaWidth As MASSizePolicy = Nothing,
                             Optional submitAreaHeight As MASSizePolicy = Nothing,
                             Optional maxContentWidth As Single = 0.0F,
                             Optional scrollEnabled As Boolean = False,
                             Optional scrollKey As String = "",
                             Optional useDefaultVisualPolish As Boolean = True) As IMASLayoutNode

            Return MASPage.Form(fields, title, description, submitArea, spacing, padding, titleHeight, descriptionHeight, submitAreaWidth, submitAreaHeight, maxContentWidth, scrollEnabled, BuildHostScrollKey(scrollKey), useDefaultVisualPolish)
        End Function

        Friend Function Form(fields As IEnumerable(Of MASFormField),
                             Optional title As MASControlBase = Nothing,
                             Optional description As MASControlBase = Nothing,
                             Optional submitArea As MASControlBase = Nothing,
                             Optional spacing As Single = 16.0F,
                             Optional padding As MASLayoutThickness = Nothing,
                             Optional titleHeight As MASSizePolicy = Nothing,
                             Optional descriptionHeight As MASSizePolicy = Nothing,
                             Optional submitAreaWidth As MASSizePolicy = Nothing,
                             Optional submitAreaHeight As MASSizePolicy = Nothing,
                             Optional maxContentWidth As Single = 0.0F,
                             Optional scrollEnabled As Boolean = False,
                             Optional scrollKey As String = "",
                             Optional useDefaultVisualPolish As Boolean = True) As IMASLayoutNode

            Return MASPage.Form(fields, title, description, submitArea, spacing, padding, titleHeight, descriptionHeight, submitAreaWidth, submitAreaHeight, maxContentWidth, scrollEnabled, BuildHostScrollKey(scrollKey), useDefaultVisualPolish)
        End Function
        Friend Function Form(sections As IEnumerable(Of MASFormSection),
                             Optional title As MASControlBase = Nothing,
                             Optional description As MASControlBase = Nothing,
                             Optional actions As IMASLayoutNode = Nothing,
                             Optional spacing As Single = 16.0F,
                             Optional padding As MASLayoutThickness = Nothing,
                             Optional titleHeight As MASSizePolicy = Nothing,
                             Optional descriptionHeight As MASSizePolicy = Nothing,
                             Optional actionsWidth As MASSizePolicy = Nothing,
                             Optional actionsHeight As MASSizePolicy = Nothing,
                             Optional maxContentWidth As Single = 0.0F,
                             Optional scrollEnabled As Boolean = False,
                             Optional scrollKey As String = "",
                             Optional useDefaultVisualPolish As Boolean = True) As IMASLayoutNode

            Return MASPage.Form(sections, title, description, actions, spacing, padding, titleHeight, descriptionHeight, actionsWidth, actionsHeight, maxContentWidth, scrollEnabled, BuildHostScrollKey(scrollKey), useDefaultVisualPolish)
        End Function

        Friend Function Section(title As MASControlBase,
                                fields As IEnumerable(Of MASFormField),
                                Optional description As MASControlBase = Nothing,
                                Optional spacing As Single = 14.0F,
                                Optional padding As MASLayoutThickness = Nothing,
                                Optional margin As MASLayoutThickness = Nothing,
                                Optional key As String = "",
                                Optional useDefaultVisualPolish As Boolean = True) As MASFormSection

            Return MASPage.Section(title, fields, description, spacing, padding, margin, key, useDefaultVisualPolish)
        End Function

        Friend Function Section(titleText As String,
                                fields As IEnumerable(Of MASFormField),
                                Optional descriptionText As String = "",
                                Optional spacing As Single = 14.0F,
                                Optional padding As MASLayoutThickness = Nothing,
                                Optional margin As MASLayoutThickness = Nothing,
                                Optional key As String = "",
                                Optional useDefaultVisualPolish As Boolean = True) As MASFormSection

            Dim titleLabel As MASLabel = GetTextRecipeLabel("Form.Section.Title", titleText, key, AddressOf MASPageLabelRecipeFactory.CreateSectionTitle)
            Dim descriptionLabel As MASLabel = Nothing

            If Not String.IsNullOrWhiteSpace(descriptionText) Then
                descriptionLabel = GetTextRecipeLabel("Form.Section.Description", descriptionText, key, AddressOf MASPageLabelRecipeFactory.CreateSectionDescription)
            End If

            Return MASPage.Section(titleLabel, fields, descriptionLabel, spacing, padding, margin, key, useDefaultVisualPolish)
        End Function

        Friend Function Field(label As MASControlBase,
                      fieldControl As MASControlBase,
                      Optional labelWidth As MASSizePolicy = Nothing,
                      Optional fieldWidth As MASSizePolicy = Nothing,
                      Optional fieldHeight As MASSizePolicy = Nothing,
                      Optional rowHeight As MASSizePolicy = Nothing,
                      Optional spacing As Single = 12.0F,
                      Optional margin As MASLayoutThickness = Nothing,
                      Optional key As String = "") As MASFormField

            Return MASPage.Field(label, fieldControl, labelWidth, fieldWidth, fieldHeight, rowHeight, spacing, margin, key)

        End Function

        Friend Function Field(labelText As String,
                      fieldControl As MASControlBase,
                      Optional labelWidth As MASSizePolicy = Nothing,
                      Optional fieldWidth As MASSizePolicy = Nothing,
                      Optional fieldHeight As MASSizePolicy = Nothing,
                      Optional rowHeight As MASSizePolicy = Nothing,
                      Optional spacing As Single = 12.0F,
                      Optional margin As MASLayoutThickness = Nothing,
                      Optional key As String = "") As MASFormField

            Dim labelControl As MASLabel = GetTextRecipeLabel("Form.Field.Label", labelText, key, AddressOf MASPageLabelRecipeFactory.CreateFormFieldLabel)
            Return MASPage.Field(labelControl, fieldControl, labelWidth, fieldWidth, fieldHeight, rowHeight, spacing, margin, key)

        End Function
        Friend Function Item(control As MASControlBase,
                     Optional height As MASSizePolicy = Nothing,
                     Optional width As MASSizePolicy = Nothing,
                     Optional margin As MASLayoutThickness = Nothing,
                     Optional key As String = "") As MASLayoutItem

            Return MASPage.Item(control, height, width, margin, key)

        End Function
        Friend Function ActionsRow(primary As MASControlBase,
                                   Optional secondary As MASControlBase = Nothing,
                                   Optional spacing As Single = 10.0F,
                                   Optional padding As MASLayoutThickness = Nothing,
                                   Optional key As String = "",
                                   Optional useDefaultVisualPolish As Boolean = True) As IMASLayoutNode

            Return MASPage.ActionsRow(primary, secondary, spacing, padding, key, useDefaultVisualPolish)
        End Function

        Friend Function ActionsRow(controls As IEnumerable(Of MASControlBase),
                                   Optional spacing As Single = 10.0F,
                                   Optional padding As MASLayoutThickness = Nothing,
                                   Optional key As String = "",
                                   Optional useDefaultVisualPolish As Boolean = True) As IMASLayoutNode

            Return MASPage.ActionsRow(controls, spacing, padding, key, useDefaultVisualPolish)
        End Function

        Friend Function Actions(control As MASControlBase,
                                Optional width As MASSizePolicy = Nothing,
                                Optional height As MASSizePolicy = Nothing,
                                Optional margin As MASLayoutThickness = Nothing,
                                Optional key As String = "") As MASLayoutItem

            Return MASPage.Actions(control, width, height, margin, key)
        End Function


        Friend Function SettingsPage(sections As IEnumerable(Of MASSettingsSection),
                                     Optional title As MASControlBase = Nothing,
                                     Optional description As MASControlBase = Nothing,
                                     Optional actions As IMASLayoutNode = Nothing,
                                     Optional spacing As Single = 18.0F,
                                     Optional padding As MASLayoutThickness = Nothing,
                                     Optional titleHeight As MASSizePolicy = Nothing,
                                     Optional descriptionHeight As MASSizePolicy = Nothing,
                                     Optional actionsWidth As MASSizePolicy = Nothing,
                                     Optional actionsHeight As MASSizePolicy = Nothing,
                                     Optional maxContentWidth As Single = 760.0F,
                                     Optional scrollEnabled As Boolean = True,
                                     Optional scrollKey As String = "",
                                     Optional useDefaultVisualPolish As Boolean = True) As IMASLayoutNode

            Return MASPage.SettingsPage(sections, title, description, actions, spacing, padding, titleHeight, descriptionHeight, actionsWidth, actionsHeight, maxContentWidth, scrollEnabled, BuildHostScrollKey(scrollKey), useDefaultVisualPolish)
        End Function

        Friend Function SettingsSection(title As MASControlBase,
                                        rows As IEnumerable(Of MASSettingsRow),
                                        Optional description As MASControlBase = Nothing,
                                        Optional spacing As Single = 12.0F,
                                        Optional padding As MASLayoutThickness = Nothing,
                                        Optional margin As MASLayoutThickness = Nothing,
                                        Optional key As String = "",
                                        Optional useDefaultVisualPolish As Boolean = True) As MASSettingsSection

            Return MASPage.SettingsSection(title, rows, description, spacing, padding, margin, key, useDefaultVisualPolish)
        End Function

        Friend Function SettingsSection(titleText As String,
                                        rows As IEnumerable(Of MASSettingsRow),
                                        Optional descriptionText As String = "",
                                        Optional spacing As Single = 12.0F,
                                        Optional padding As MASLayoutThickness = Nothing,
                                        Optional margin As MASLayoutThickness = Nothing,
                                        Optional key As String = "",
                                        Optional useDefaultVisualPolish As Boolean = True) As MASSettingsSection

            Dim titleControl As MASLabel = Nothing
            Dim descriptionControl As MASLabel = Nothing

            If Not String.IsNullOrWhiteSpace(titleText) Then
                titleControl = GetTextRecipeLabel("Settings.Section.Title", titleText, key, AddressOf MASPageLabelRecipeFactory.CreateSettingsTitle)
            End If

            If Not String.IsNullOrWhiteSpace(descriptionText) Then
                descriptionControl = GetTextRecipeLabel("Settings.Section.Description", descriptionText, key, AddressOf MASPageLabelRecipeFactory.CreateSettingsDescription)
            End If

            Return MASPage.SettingsSection(titleControl, rows, descriptionControl, spacing, padding, margin, key, useDefaultVisualPolish)
        End Function

        Friend Function SettingRow(label As MASControlBase,
                                   editor As MASControlBase,
                                   Optional description As MASControlBase = Nothing,
                                   Optional labelColumnWidth As MASSizePolicy = Nothing,
                                   Optional editorWidth As MASSizePolicy = Nothing,
                                   Optional editorHeight As MASSizePolicy = Nothing,
                                   Optional rowHeight As MASSizePolicy = Nothing,
                                   Optional spacing As Single = 18.0F,
                                   Optional padding As MASLayoutThickness = Nothing,
                                   Optional margin As MASLayoutThickness = Nothing,
                                   Optional key As String = "",
                                   Optional useDefaultVisualPolish As Boolean = True) As MASSettingsRow

            Return MASPage.SettingRow(label, editor, description, labelColumnWidth, editorWidth, editorHeight, rowHeight, spacing, padding, margin, key, useDefaultVisualPolish)
        End Function

        Friend Function SettingRow(labelText As String,
                                   editor As MASControlBase,
                                   Optional descriptionText As String = "",
                                   Optional labelColumnWidth As MASSizePolicy = Nothing,
                                   Optional editorWidth As MASSizePolicy = Nothing,
                                   Optional editorHeight As MASSizePolicy = Nothing,
                                   Optional rowHeight As MASSizePolicy = Nothing,
                                   Optional spacing As Single = 18.0F,
                                   Optional padding As MASLayoutThickness = Nothing,
                                   Optional margin As MASLayoutThickness = Nothing,
                                   Optional key As String = "",
                                   Optional useDefaultVisualPolish As Boolean = True) As MASSettingsRow

            Dim labelControl As MASLabel = GetTextRecipeLabel("Settings.Row.Label", labelText, key, AddressOf MASPageLabelRecipeFactory.CreateSettingsRowLabel)
            Dim descriptionControl As MASLabel = Nothing

            If Not String.IsNullOrWhiteSpace(descriptionText) Then
                descriptionControl = GetTextRecipeLabel("Settings.Row.Description", descriptionText, key, AddressOf MASPageLabelRecipeFactory.CreateSettingsRowDescription)
            End If

            Return MASPage.SettingRow(labelControl, editor, descriptionControl, labelColumnWidth, editorWidth, editorHeight, rowHeight, spacing, padding, margin, key, useDefaultVisualPolish)
        End Function


        Friend Function EditorPage(sections As IEnumerable(Of MASFormSection),
                                   Optional title As MASControlBase = Nothing,
                                   Optional description As MASControlBase = Nothing,
                                   Optional actions As IMASLayoutNode = Nothing,
                                   Optional spacing As Single = 16.0F,
                                   Optional padding As MASLayoutThickness = Nothing,
                                   Optional titleHeight As MASSizePolicy = Nothing,
                                   Optional descriptionHeight As MASSizePolicy = Nothing,
                                   Optional actionsWidth As MASSizePolicy = Nothing,
                                   Optional actionsHeight As MASSizePolicy = Nothing,
                                   Optional maxContentWidth As Single = 760.0F,
                                   Optional scrollEnabled As Boolean = True,
                                   Optional scrollKey As String = "",
                                   Optional useDefaultVisualPolish As Boolean = True) As IMASLayoutNode

            Return MASPage.EditorPage(sections, title, description, actions, spacing, padding, titleHeight, descriptionHeight, actionsWidth, actionsHeight, maxContentWidth, scrollEnabled, BuildHostScrollKey(scrollKey), useDefaultVisualPolish)
        End Function

        Friend Function EditorPage(fields As IEnumerable(Of MASFormField),
                                   Optional title As MASControlBase = Nothing,
                                   Optional description As MASControlBase = Nothing,
                                   Optional submitArea As MASControlBase = Nothing,
                                   Optional spacing As Single = 16.0F,
                                   Optional padding As MASLayoutThickness = Nothing,
                                   Optional titleHeight As MASSizePolicy = Nothing,
                                   Optional descriptionHeight As MASSizePolicy = Nothing,
                                   Optional submitAreaWidth As MASSizePolicy = Nothing,
                                   Optional submitAreaHeight As MASSizePolicy = Nothing,
                                   Optional maxContentWidth As Single = 760.0F,
                                   Optional scrollEnabled As Boolean = True,
                                   Optional scrollKey As String = "",
                                   Optional useDefaultVisualPolish As Boolean = True) As IMASLayoutNode

            Return MASPage.EditorPage(fields, title, description, submitArea, spacing, padding, titleHeight, descriptionHeight, submitAreaWidth, submitAreaHeight, maxContentWidth, scrollEnabled, BuildHostScrollKey(scrollKey), useDefaultVisualPolish)
        End Function

        Friend Function WizardPage(stepTitle As MASControlBase,
                                   Optional stepDescription As MASControlBase = Nothing,
                                   Optional content As IMASLayoutNode = Nothing,
                                   Optional actions As IMASLayoutNode = Nothing,
                                   Optional progress As MASControlBase = Nothing,
                                   Optional spacing As Single = 16.0F,
                                   Optional padding As MASLayoutThickness = Nothing,
                                   Optional titleHeight As MASSizePolicy = Nothing,
                                   Optional descriptionHeight As MASSizePolicy = Nothing,
                                   Optional contentHeight As MASSizePolicy = Nothing,
                                   Optional actionsWidth As MASSizePolicy = Nothing,
                                   Optional actionsHeight As MASSizePolicy = Nothing,
                                   Optional maxContentWidth As Single = 760.0F,
                                   Optional scrollEnabled As Boolean = True,
                                   Optional scrollKey As String = "",
                                   Optional useDefaultVisualPolish As Boolean = True) As IMASLayoutNode

            Return MASPage.WizardPage(stepTitle, stepDescription, content, actions, progress, spacing, padding, titleHeight, descriptionHeight, contentHeight, actionsWidth, actionsHeight, maxContentWidth, scrollEnabled, BuildHostScrollKey(scrollKey), useDefaultVisualPolish)
        End Function

        Friend Function WizardPage(stepTitle As MASControlBase,
                                   stepDescription As MASControlBase,
                                   content As MASControlBase,
                                   Optional actions As IMASLayoutNode = Nothing,
                                   Optional progress As MASControlBase = Nothing,
                                   Optional spacing As Single = 16.0F,
                                   Optional padding As MASLayoutThickness = Nothing,
                                   Optional titleHeight As MASSizePolicy = Nothing,
                                   Optional descriptionHeight As MASSizePolicy = Nothing,
                                   Optional contentHeight As MASSizePolicy = Nothing,
                                   Optional actionsWidth As MASSizePolicy = Nothing,
                                   Optional actionsHeight As MASSizePolicy = Nothing,
                                   Optional maxContentWidth As Single = 760.0F,
                                   Optional scrollEnabled As Boolean = True,
                                   Optional scrollKey As String = "",
                                   Optional useDefaultVisualPolish As Boolean = True) As IMASLayoutNode

            Return MASPage.WizardPage(stepTitle, stepDescription, content, actions, progress, spacing, padding, titleHeight, descriptionHeight, contentHeight, actionsWidth, actionsHeight, maxContentWidth, scrollEnabled, BuildHostScrollKey(scrollKey), useDefaultVisualPolish)
        End Function

        Friend Function WizardActionsRow(nextButton As MASControlBase,
                                         Optional backButton As MASControlBase = Nothing,
                                         Optional cancelButton As MASControlBase = Nothing,
                                         Optional spacing As Single = 10.0F,
                                         Optional padding As MASLayoutThickness = Nothing,
                                         Optional key As String = "",
                                         Optional useDefaultVisualPolish As Boolean = True) As IMASLayoutNode

            Return MASPage.WizardActionsRow(nextButton, backButton, cancelButton, spacing, padding, key, useDefaultVisualPolish)
        End Function



        Friend Function DetailsPage(sections As IEnumerable(Of MASDetailsSection),
                                    Optional title As MASControlBase = Nothing,
                                    Optional description As MASControlBase = Nothing,
                                    Optional actions As IMASLayoutNode = Nothing,
                                    Optional spacing As Single = 18.0F,
                                    Optional padding As MASLayoutThickness = Nothing,
                                    Optional titleHeight As MASSizePolicy = Nothing,
                                    Optional descriptionHeight As MASSizePolicy = Nothing,
                                    Optional actionsWidth As MASSizePolicy = Nothing,
                                    Optional actionsHeight As MASSizePolicy = Nothing,
                                    Optional maxContentWidth As Single = 760.0F,
                                    Optional scrollEnabled As Boolean = True,
                                    Optional scrollKey As String = "",
                                    Optional useDefaultVisualPolish As Boolean = True) As IMASLayoutNode

            Return MASPage.DetailsPage(sections, title, description, actions, spacing, padding, titleHeight, descriptionHeight, actionsWidth, actionsHeight, maxContentWidth, scrollEnabled, BuildHostScrollKey(scrollKey), useDefaultVisualPolish)
        End Function

        Friend Function DetailsSection(title As MASControlBase,
                                       rows As IEnumerable(Of MASDetailsRow),
                                       Optional description As MASControlBase = Nothing,
                                       Optional spacing As Single = 12.0F,
                                       Optional padding As MASLayoutThickness = Nothing,
                                       Optional margin As MASLayoutThickness = Nothing,
                                       Optional key As String = "",
                                       Optional useDefaultVisualPolish As Boolean = True) As MASDetailsSection

            Return MASPage.DetailsSection(title, rows, description, spacing, padding, margin, key, useDefaultVisualPolish)
        End Function

        Friend Function DetailsSection(titleText As String,
                                       rows As IEnumerable(Of MASDetailsRow),
                                       Optional descriptionText As String = "",
                                       Optional spacing As Single = 12.0F,
                                       Optional padding As MASLayoutThickness = Nothing,
                                       Optional margin As MASLayoutThickness = Nothing,
                                       Optional key As String = "",
                                       Optional useDefaultVisualPolish As Boolean = True) As MASDetailsSection

            Dim titleControl As MASLabel = Nothing
            Dim descriptionControl As MASLabel = Nothing

            If Not String.IsNullOrWhiteSpace(titleText) Then
                titleControl = GetTextRecipeLabel("Details.Section.Title", titleText, key, AddressOf MASPageLabelRecipeFactory.CreateDetailsTitle)
            End If

            If Not String.IsNullOrWhiteSpace(descriptionText) Then
                descriptionControl = GetTextRecipeLabel("Details.Section.Description", descriptionText, key, AddressOf MASPageLabelRecipeFactory.CreateDetailsDescription)
            End If

            Return MASPage.DetailsSection(titleControl, rows, descriptionControl, spacing, padding, margin, key, useDefaultVisualPolish)
        End Function

        Friend Function DetailsRow(label As MASControlBase,
                                   valueControl As MASControlBase,
                                   Optional description As MASControlBase = Nothing,
                                   Optional labelColumnWidth As MASSizePolicy = Nothing,
                                   Optional valueWidth As MASSizePolicy = Nothing,
                                   Optional valueHeight As MASSizePolicy = Nothing,
                                   Optional rowHeight As MASSizePolicy = Nothing,
                                   Optional spacing As Single = 18.0F,
                                   Optional padding As MASLayoutThickness = Nothing,
                                   Optional margin As MASLayoutThickness = Nothing,
                                   Optional key As String = "",
                                   Optional useDefaultVisualPolish As Boolean = True) As MASDetailsRow

            Return MASPage.DetailsRow(label, valueControl, description, labelColumnWidth, valueWidth, valueHeight, rowHeight, spacing, padding, margin, key, useDefaultVisualPolish)
        End Function

        Friend Function DetailsRow(labelText As String,
                                   valueText As String,
                                   Optional descriptionText As String = "",
                                   Optional labelColumnWidth As MASSizePolicy = Nothing,
                                   Optional valueWidth As MASSizePolicy = Nothing,
                                   Optional valueHeight As MASSizePolicy = Nothing,
                                   Optional rowHeight As MASSizePolicy = Nothing,
                                   Optional spacing As Single = 18.0F,
                                   Optional padding As MASLayoutThickness = Nothing,
                                   Optional margin As MASLayoutThickness = Nothing,
                                   Optional key As String = "",
                                   Optional useDefaultVisualPolish As Boolean = True) As MASDetailsRow

            Dim labelControl As MASLabel = GetTextRecipeLabel("Details.Row.Label", labelText, key, AddressOf MASPageLabelRecipeFactory.CreateDetailsRowLabel)
            Dim valueControl As MASLabel = GetTextRecipeLabel("Details.Row.Value", valueText, key, AddressOf MASPageLabelRecipeFactory.CreateDetailsValue)
            Dim descriptionControl As MASLabel = Nothing

            If Not String.IsNullOrWhiteSpace(descriptionText) Then
                descriptionControl = GetTextRecipeLabel("Details.Row.Description", descriptionText, key, AddressOf MASPageLabelRecipeFactory.CreateDetailsRowDescription)
            End If

            Return MASPage.DetailsRow(labelControl, valueControl, descriptionControl, labelColumnWidth, valueWidth, valueHeight, rowHeight, spacing, padding, margin, key, useDefaultVisualPolish)
        End Function

        Friend Function EmptyStatePage(title As MASControlBase,
                                       Optional message As MASControlBase = Nothing,
                                       Optional actions As IMASLayoutNode = Nothing,
                                       Optional illustration As MASControlBase = Nothing,
                                       Optional spacing As Single = 12.0F,
                                       Optional padding As MASLayoutThickness = Nothing,
                                       Optional maxContentWidth As Single = 560.0F,
                                       Optional centerVertically As Boolean = True,
                                       Optional useDefaultVisualPolish As Boolean = True) As IMASLayoutNode

            Return MASPage.EmptyStatePage(title, message, actions, illustration, spacing, padding, maxContentWidth, centerVertically, useDefaultVisualPolish)
        End Function

        Friend Function EmptyStatePage(titleText As String,
                                       Optional messageText As String = "",
                                       Optional actions As IMASLayoutNode = Nothing,
                                       Optional illustration As MASControlBase = Nothing,
                                       Optional spacing As Single = 12.0F,
                                       Optional padding As MASLayoutThickness = Nothing,
                                       Optional maxContentWidth As Single = 560.0F,
                                       Optional centerVertically As Boolean = True,
                                       Optional useDefaultVisualPolish As Boolean = True) As IMASLayoutNode

            Dim titleControl As MASLabel = GetTextRecipeLabel("EmptyState.Title", titleText, String.Empty, AddressOf MASPageLabelRecipeFactory.CreateEmptyStateTitle)
            Dim messageControl As MASLabel = Nothing

            If Not String.IsNullOrWhiteSpace(messageText) Then
                messageControl = GetTextRecipeLabel("EmptyState.Message", messageText, String.Empty, AddressOf MASPageLabelRecipeFactory.CreateEmptyStateMessage)
            End If

            Return MASPage.EmptyStatePage(titleControl, messageControl, actions, illustration, spacing, padding, maxContentWidth, centerVertically, useDefaultVisualPolish)
        End Function

        ''' <summary>
        ''' Starts one host-owned layout-factory build pass.
        ''' Text recipe labels created through this facade are then keyed by stable call order or explicit row/section keys,
        ''' so rebuild-heavy pages do not allocate new MASLabel instances on every resize/scroll refresh.
        ''' </summary>
        Friend Sub BeginLayoutFactoryBuild()
            _textRecipeBuildOrdinal = 0
            _textRecipeUsedKeys.Clear()
            _isInsideLayoutFactoryBuild = True
        End Sub

        ''' <summary>
        ''' Completes the current host-owned layout-factory build pass and releases stale generated labels that no longer
        ''' belong to the page recipe. Existing live labels remain normal controls and stay owned by the composition applier.
        ''' </summary>
        Friend Sub EndLayoutFactoryBuild()
            If Not _isInsideLayoutFactoryBuild Then Return

            For Each cacheKey As String In New List(Of String)(_textRecipeControls.Keys)
                If Not _textRecipeUsedKeys.Contains(cacheKey) Then
                    _textRecipeControls.Remove(cacheKey)
                End If
            Next

            _textRecipeUsedKeys.Clear()
            _isInsideLayoutFactoryBuild = False
        End Sub

        ''' <summary>
        ''' Releases host-generated text recipe labels when the owning composition runtime is cleared.
        ''' </summary>
        Friend Sub ClearTextRecipeCache()
            _textRecipeControls.Clear()
            _textRecipeUsedKeys.Clear()
            _textRecipeBuildOrdinal = 0
            _isInsideLayoutFactoryBuild = False
        End Sub

        Private Function GetTextRecipeLabel(kind As String,
                                            text As String,
                                            explicitKey As String,
                                            factory As Func(Of String, MASLabel)) As MASLabel

            If factory Is Nothing Then Throw New ArgumentNullException(NameOf(factory))

            Dim cacheKey As String = BuildTextRecipeCacheKey(kind, explicitKey)
            Dim label As MASLabel = Nothing

            If Not _textRecipeControls.TryGetValue(cacheKey, label) OrElse label Is Nothing Then
                label = factory.Invoke(If(text, String.Empty))
                _textRecipeControls(cacheKey) = label
            End If

            label.Text = If(text, String.Empty)

            If _isInsideLayoutFactoryBuild Then
                _textRecipeUsedKeys.Add(cacheKey)
            End If

            Return label
        End Function

        Private Function BuildTextRecipeCacheKey(kind As String, explicitKey As String) As String
            Dim normalizedKind As String = If(kind, String.Empty).Trim()
            If normalizedKind.Length = 0 Then normalizedKind = "Label"

            Dim normalizedKey As String = If(explicitKey, String.Empty).Trim()
            If normalizedKey.Length > 0 Then
                Return normalizedKind & "|Key|" & normalizedKey
            End If

            Dim ordinal As Integer = _textRecipeBuildOrdinal
            _textRecipeBuildOrdinal += 1

            Return normalizedKind & "|Ordinal|" & ordinal.ToString(Global.System.Globalization.CultureInfo.InvariantCulture)
        End Function

        Private Function BuildHostScrollKey(scrollKey As String) As String
            Return _runtime.BuildScrollKey(scrollKey)
        End Function

        Friend Function Show(page As IMASLayoutNode) As Boolean
            Return _runtime.SetLayout(page)
        End Function

        Friend Function ShowFactory(factory As Func(Of IMASLayoutNode),
                                    Optional applyImmediately As Boolean = True) As Boolean
            Return _runtime.SetLayoutFactory(factory, applyImmediately)
        End Function

    End Class

End Namespace
