Option Strict On
Option Explicit On

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

Namespace Nexamas.UI.Application

    ''' <summary>
    ''' Official Nexamas UI Application settings page builder for a MASApplicationWindow.
    ''' The page owns only Application-level settings UI. It never calculates control sizes, never writes bounds,
    ''' and never introduces a parallel layout or sizing system.
    ''' </summary>
    Friend NotInheritable Class MASApplicationSettingsPage
        Implements IDisposable

        Private ReadOnly _window As MASApplicationWindow
        Private ReadOnly _options As MASApplicationSettingsPageOptions
        Private ReadOnly _ownedSections As New List(Of IDisposable)()
        Private ReadOnly _ownedControls As New List(Of MASControlBase)()
        Private _disposed As Boolean

        Private Sub New(window As MASApplicationWindow,
                        options As MASApplicationSettingsPageOptions)
            If window Is Nothing Then Throw New ArgumentNullException(NameOf(window))
            _window = window
            _options = MASApplicationSettingsPageOptions.Normalize(options)
        End Sub

        Friend Shared Function CreateFor(window As MASApplicationWindow,
                                         Optional options As MASApplicationSettingsPageOptions = Nothing) As MASApplicationSettingsPage
            Return New MASApplicationSettingsPage(window, options)
        End Function

        Friend Shared Function Show(window As MASApplicationWindow,
                                    Optional options As MASApplicationSettingsPageOptions = Nothing) As MASApplicationSettingsPageResult
            Using page As MASApplicationSettingsPage = CreateFor(window, options)
                Return page.Show()
            End Using
        End Function

        Friend ReadOnly Property Options As MASApplicationSettingsPageOptions
            Get
                Return _options.Clone()
            End Get
        End Property

        Friend Function Show() As MASApplicationSettingsPageResult
            ThrowIfDisposed()

            If _window Is Nothing OrElse _window.IsDisposed Then
                Return MASApplicationSettingsPageResult.Failed(MASApplicationSettingsPageResultStatus.WindowUnavailable, "The owning MASApplicationWindow is unavailable.")
            End If

            DisposeOwnedSections()
            _ownedControls.Clear()

            If _options.ClearExistingControls Then
                _window.Controls.Clear()
            End If

            Dim pageTitle As MASTitle = CreateOptionalTitleLabel()
            Dim pageSubtitle As MASLabel = CreateOptionalSubtitleLabel()

            If pageTitle IsNot Nothing Then _ownedControls.Add(pageTitle)
            If pageSubtitle IsNot Nothing Then _ownedControls.Add(pageSubtitle)

            Dim sizingInstance As MASSizingSettingsSectionInstance = Nothing

            If _options.IncludeSizingSection Then
                sizingInstance = MASSizingSettingsSection.Create().CreateInstance(_window, _options)
                _ownedSections.Add(sizingInstance)
                _ownedControls.AddRange(sizingInstance.Controls)
            End If

            If _ownedControls.Count = 0 Then
                Return MASApplicationSettingsPageResult.Failed(MASApplicationSettingsPageResultStatus.NoSections, "No Application settings sections were enabled.")
            End If

            Dim applied As Boolean = _window.Controls.LayoutPage(
                Sub(page As MASApplicationLayoutPageBuilder)
                    MASApplicationSettingsLayoutPolicy.ConfigureSettingsPage(page, _options)

                    Dim presentation As MASPresentationPageBuilder = MASPresentationPage.BeginPreconfigured(page)
                    presentation.Header(pageTitle, pageSubtitle)

                    If sizingInstance IsNot Nothing Then
                        sizingInstance.AddToPage(presentation)
                    End If
                End Sub)

            If Not applied Then
                DisposeOwnedSections()
                Return MASApplicationSettingsPageResult.Failed(MASApplicationSettingsPageResultStatus.LayoutFailed, "The Application settings page layout could not be applied.")
            End If

            Return MASApplicationSettingsPageResult.Shown(Array.AsReadOnly(_ownedControls.ToArray()))
        End Function



        Private Function CreateOptionalTitleLabel() As MASTitle
            Dim text As String = If(_options.Title, String.Empty).Trim()
            If text.Length = 0 Then Return Nothing

            Return _window.Controls.CreateTitle(text)
        End Function

        Private Function CreateOptionalSubtitleLabel() As MASLabel
            Dim text As String = If(_options.Subtitle, String.Empty).Trim()
            If text.Length = 0 Then Return Nothing

            Return _window.Controls.CreateLabel(text,
                Sub(label As MASLabel)
                    label.LabelVariant = MASLabelVariant.Body
                    label.TextRole = MASLabelTextRole.Secondary
                    label.MultiLine = True
                    label.MaxLines = 3
                End Sub)
        End Function

        Public Sub Dispose() Implements IDisposable.Dispose
            If _disposed Then Return
            _disposed = True
            DisposeOwnedSections()
            _ownedControls.Clear()
        End Sub

        Private Sub DisposeOwnedSections()
            For Each section As IDisposable In _ownedSections.ToArray()
                If section Is Nothing Then Continue For
                Try
                    section.Dispose()
                Catch masCaughtException As Exception
                    MASExceptionSilencer.SwallowBoundary(masCaughtException)
                End Try
            Next

            _ownedSections.Clear()
        End Sub

        Private Sub ThrowIfDisposed()
            If _disposed Then Throw New ObjectDisposedException(NameOf(MASApplicationSettingsPage))
        End Sub

    End Class

End Namespace
