Option Strict On
Option Explicit On

Imports System
Imports System.Diagnostics
Imports Nexamas.UI.Application
Imports Nexamas.UI.Layout

Namespace Nexamas.UI.Localization

    ''' <summary>
    ''' Official public host gateway for the Nexamas UI-owned Localization / RTL product surface.
    ''' </summary>
    ''' <remarks>
    ''' This gateway exposes a ready read-only/product-preview page only. It does not expose localization
    ''' snapshots, culture catalogs, string catalogs, readiness reports, thread-culture mutation, resource
    ''' loading, or a public translation API. Localization facts remain owned by LocalizationSystem.
    ''' </remarks>
    Public NotInheritable Class MASLocalizationRtl
        Private Sub New()
        End Sub

        ''' <summary>
        ''' Attaches the official Nexamas UI-owned Localization / RTL page to a MASApplicationWindow.
        ''' External hosts receive a ready product page and never read localization contracts or catalogs.
        ''' </summary>
        Public Shared Function AttachPage(window As MASApplicationWindow) As IDisposable
            If window Is Nothing Then Throw New ArgumentNullException(NameOf(window))
            Return AttachPageThroughUiDispatcher(window, Nothing, hasExternalPage:=False)
        End Function

        ''' <summary>
        ''' Attaches the official Nexamas UI-owned Localization / RTL content to an existing
        ''' Application page-builder scope such as MASApplicationWindow.Pages. The host supplies only
        ''' the current MASApplicationWindow and MASApplicationLayoutPageBuilder; Nexamas UI still owns
        ''' culture facts, direction rows, formatting previews, expansion rows, controls, and page layout.
        ''' </summary>
        Public Shared Function AttachPage(window As MASApplicationWindow,
                                          page As MASApplicationLayoutPageBuilder) As IDisposable
            If window Is Nothing Then Throw New ArgumentNullException(NameOf(window))
            If page Is Nothing Then Throw New ArgumentNullException(NameOf(page))

            Return AttachPageThroughUiDispatcher(window, page, hasExternalPage:=True)
        End Function

        Private Shared Function AttachPageThroughUiDispatcher(window As MASApplicationWindow,
                                                              page As MASApplicationLayoutPageBuilder,
                                                              hasExternalPage As Boolean) As IDisposable
            If window Is Nothing Then Throw New ArgumentNullException(NameOf(window))
            If window.IsDisposed Then Throw New ObjectDisposedException(NameOf(MASApplicationWindow))

            Dim attachedPage As IDisposable = Nothing
            Dim capturedException As Exception = Nothing
            Dim executedOnUiThread As Boolean = False

            Dim invoked As Boolean = window.InvokeOnUiThreadForInternalGateway(
                Sub()
                    executedOnUiThread = True

                    If window.IsDisposed Then
                        capturedException = New ObjectDisposedException(NameOf(MASApplicationWindow))
                        Return
                    End If

                    Try
                        attachedPage = AttachPageOnUiThread(window, page, hasExternalPage)
                    Catch ex As Exception
                        capturedException = ex
                    End Try
                End Sub,
                "MASLocalizationRtl.AttachPage.Dispatcher")

            If Not invoked OrElse Not executedOnUiThread Then
                Throw CreateAttachPageDispatcherFailureException()
            End If

            If capturedException IsNot Nothing Then Throw capturedException

            If window.IsDisposed Then
                DisposeAttachedPageAfterLateWindowDispose(attachedPage)
                Throw New ObjectDisposedException(NameOf(MASApplicationWindow))
            End If

            Return attachedPage
        End Function

        Private Shared Function AttachPageOnUiThread(window As MASApplicationWindow,
                                                     page As MASApplicationLayoutPageBuilder,
                                                     hasExternalPage As Boolean) As IDisposable
            Dim localizationPage As New MASLocalizationRtlPage()
            Try
                If hasExternalPage Then
                    localizationPage.Build(window, page)
                Else
                    localizationPage.Build(window)
                End If
            Catch ex As Exception
                RollBackFailedAttach(localizationPage)
                ShowAttachPageError(window, ex)
                Throw CreateAttachPageFailureException(ex)
            End Try
            Return localizationPage
        End Function

        Private Shared Sub DisposeAttachedPageAfterLateWindowDispose(attachedPage As IDisposable)
            If attachedPage Is Nothing Then Return

            Try
                attachedPage.Dispose()
            Catch disposeException As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDisposeCleanup(
                    disposeException,
                    "LocalizationRtl.AttachPage.LateWindowDispose")
            End Try
        End Sub

        Private Shared Sub RollBackFailedAttach(localizationPage As MASLocalizationRtlPage)
            If localizationPage Is Nothing Then Return

            Try
                CType(localizationPage, IDisposable).Dispose()
            Catch rollbackException As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDisposeCleanup(
                    rollbackException,
                    "LocalizationRtl.AttachPage.Rollback")
            End Try
        End Sub

        Private Shared Function CreateAttachPageFailureException(ex As Exception) As InvalidOperationException
            Return New InvalidOperationException(
                "MASLocalizationRtl.AttachPage failed while building the official Localization / RTL page. The partial attach was rolled back and no successful page lifetime was returned.",
                ex)
        End Function

        Private Shared Function CreateAttachPageDispatcherFailureException() As InvalidOperationException
            Return New InvalidOperationException(
                "MASLocalizationRtl.AttachPage requires an active MASApplicationWindow UI dispatcher. No Localization / RTL page lifetime was returned.")
        End Function

        Private Shared Sub ShowAttachPageError(window As MASApplicationWindow, ex As Exception)
            Try
                If window IsNot Nothing AndAlso Not window.IsDisposed AndAlso window.Services IsNot Nothing Then
                    window.Services.Dialogs.Error(
                        message:="The Nexamas UI Localization / RTL page could not be attached.",
                        title:="Nexamas UI Localization / RTL",
                        detail:=If(ex Is Nothing, String.Empty, ex.Message),
                        ownerKey:="MAS.LocalizationRtl.AttachPage.Error")
                End If
            Catch dialogException As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDiagnosticOnly(dialogException, "LocalizationRtl.AttachPage.DialogBoundary")
            End Try
        End Sub
    End Class

End Namespace
