Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports System.Diagnostics
Imports System.Globalization
Imports Nexamas.UI.Application
Imports Nexamas.UI.Components
Imports Nexamas.UI.Controls
Imports Nexamas.UI.Layout
Imports Nexamas.UI.Presentation

Namespace Nexamas.UI.Localization

    ''' <summary>
    ''' Nexamas UI-owned internal Localization / RTL display surface.
    ''' </summary>
    ''' <remarks>
    ''' The page consumes MASLocalization.CreateSnapshot only. It does not mutate thread-culture state,
    ''' load resources, rewrite controls, mirror the external host, create a translation engine, or let
    ''' demo code own Localization / RTL logic.
    ''' </remarks>
    Friend NotInheritable Class MASLocalizationRtlPage
        Implements IDisposable

        Private Const DialogOwnerKey As String = "MAS.LocalizationRtl.Page"
        Private Const MaxCatalogPreviewRows As Integer = 256

        Friend Shared ReadOnly Property BoundedPreviewLimitForTests As Integer
            Get
                Return MaxCatalogPreviewRows
            End Get
        End Property

        Private _window As MASApplicationWindow
        Private _title As MASTitle
        Private _description As MASLabel
        Private _status As MASLabel
        Private _summary As MASLabel
        Private _culturePickerLabel As MASLabel
        Private _culturePicker As MASComboBox
        Private _cultureRows As MASListView
        Private _stringRows As MASListView
        Private _formatRows As MASListView
        Private _expansionRows As MASListView
        Private _preview As MASLabel
        Private _details As MASLabel
        Private _ownership As MASLabel
        Private _refresh As MASButton
        Private _snapshot As MASLocalizationSnapshot
        Private ReadOnly _ownedControls As New List(Of MASControlBase)()
        Private _disposed As Boolean

        Friend Sub Build(window As MASApplicationWindow)
            If window Is Nothing Then Throw New ArgumentNullException(NameOf(window))

            _window = window
            CreateControls(includeHeader:=True)
            LayoutControls()
            RefreshLocalizationSafely(showDialogOnFailure:=True)
        End Sub

        Friend Sub Build(window As MASApplicationWindow, page As MASApplicationLayoutPageBuilder)
            If window Is Nothing Then Throw New ArgumentNullException(NameOf(window))
            If page Is Nothing Then Throw New ArgumentNullException(NameOf(page))

            _window = window
            CreateControls(includeHeader:=False)
            LayoutControls(page, includeHeader:=False)
            RefreshLocalizationSafely(showDialogOnFailure:=True)
        End Sub

        Private Sub Dispose() Implements IDisposable.Dispose
            If _disposed Then Return
            _disposed = True

            Dim ownerWindow As MASApplicationWindow = _window

            If _culturePicker IsNot Nothing Then RemoveHandler _culturePicker.SelectionChanged, AddressOf HandleCultureSelectionChanged
            If _cultureRows IsNot Nothing Then RemoveHandler _cultureRows.SelectedIndexChanged, AddressOf HandleCultureRowSelectionChanged
            If _refresh IsNot Nothing Then RemoveHandler _refresh.Click, AddressOf HandleRefresh

            RemoveOwnedControls(ownerWindow)

            _snapshot = Nothing
            _window = Nothing
        End Sub

        Private Function Own(Of T As MASControlBase)(control As T) As T
            If control IsNot Nothing Then _ownedControls.Add(control)
            Return control
        End Function

        Private Sub RemoveOwnedControls(ownerWindow As MASApplicationWindow)
            For index As Integer = _ownedControls.Count - 1 To 0 Step -1
                Dim control As MASControlBase = _ownedControls(index)
                If control Is Nothing Then Continue For

                Dim removedThroughWindow As Boolean = False

                Try
                    If ownerWindow IsNot Nothing AndAlso Not ownerWindow.IsDisposed Then
                        Dim controls As MASApplicationWindowControls = ownerWindow.Controls
                        If controls.Contains(control) Then
                            controls.RemoveAndDispose(control)
                            removedThroughWindow = True
                        End If
                    End If

                    If Not removedThroughWindow Then control.Dispose()
                Catch masCaughtExceptionOwnedControlDispose As Exception
                    Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDisposeCleanup(
                        masCaughtExceptionOwnedControlDispose,
                        "MASLocalizationRtlPage.Dispose.OwnedControl")
                End Try
            Next

            _ownedControls.Clear()
            ClearControlReferences()
        End Sub

        Private Sub ClearControlReferences()
            _title = Nothing
            _description = Nothing
            _status = Nothing
            _summary = Nothing
            _culturePickerLabel = Nothing
            _culturePicker = Nothing
            _cultureRows = Nothing
            _stringRows = Nothing
            _formatRows = Nothing
            _expansionRows = Nothing
            _preview = Nothing
            _details = Nothing
            _ownership = Nothing
            _refresh = Nothing
        End Sub

        Private Sub CreateControls(includeHeader As Boolean)
            If includeHeader Then
                _title = Own(_window.Controls.AddTitle("Nexamas UI Localization / RTL"))
                _title.WithDefaultSize()
            End If

            _description = Own(_window.Controls.AddLabel(
                "Product-readable culture and RTL readiness: this Nexamas UI-owned page shows supported cultures, direction and mirroring facts, localized sample strings, culture-aware formatting, and expansion pressure. The host only attaches the page; it does not read catalogs, mutate thread culture, or create a translation engine.",
                configure:=Sub(label As MASLabel)
                               label.LabelVariant = MASLabelVariant.Body
                               label.TextRole = MASLabelTextRole.Secondary
                               label.MultiLine = True
                               label.WordWrap = True
                           End Sub))
            _description.WithDefaultSize()

            _status = Own(_window.Controls.AddLabel("Localization / RTL status: loading...",
                configure:=Sub(label As MASLabel)
                               label.LabelVariant = MASLabelVariant.Heading
                               label.TextRole = MASLabelTextRole.Primary
                               label.MultiLine = True
                               label.WordWrap = True
                           End Sub))
            _status.WithDefaultSize()

            _summary = Own(_window.Controls.AddLabel("Loading localization facts...",
                configure:=Sub(label As MASLabel)
                               label.LabelVariant = MASLabelVariant.Body
                               label.TextRole = MASLabelTextRole.Primary
                               label.MultiLine = True
                               label.WordWrap = True
                           End Sub))
            _summary.WithDefaultSize()

            _culturePickerLabel = Own(_window.Controls.AddLabel("Preview culture",
                configure:=Sub(label As MASLabel)
                               label.LabelVariant = MASLabelVariant.Caption
                               label.TextRole = MASLabelTextRole.Muted
                           End Sub))
            _culturePickerLabel.WithDefaultSize()

            _culturePicker = Own(_window.Controls.AddComboBox(items:=New String() {"Loading cultures..."}, selectedIndex:=0))
            _culturePicker.WithSize(MASSize.Compact)
            AddHandler _culturePicker.SelectionChanged, AddressOf HandleCultureSelectionChanged

            _cultureRows = Own(_window.Controls.AddListView(configure:=Sub(view As MASListView)
                                                            view.WithDetailsView()
                                                            view.StandaloneChrome()
                                                            view.AddColumn("Culture", 120.0F)
                                                            view.AddColumn("Direction", 140.0F)
                                                            view.AddColumn("Layout flow", 150.0F)
                                                            view.AddColumn("Formatting facts", 460.0F)
                                                        End Sub))
            _cultureRows.WithDefaultSize()
            AddHandler _cultureRows.SelectedIndexChanged, AddressOf HandleCultureRowSelectionChanged

            _stringRows = Own(_window.Controls.AddListView(configure:=Sub(view As MASListView)
                                                           view.WithDetailsView()
                                                           view.StandaloneChrome()
                                                           view.AddColumn("String key", 230.0F)
                                                           view.AddColumn("English", 220.0F)
                                                           view.AddColumn("German", 240.0F)
                                                           view.AddColumn("Arabic", 240.0F)
                                                       End Sub))
            _stringRows.WithDefaultSize()

            _formatRows = Own(_window.Controls.AddListView(configure:=Sub(view As MASListView)
                                                           view.WithDetailsView()
                                                           view.StandaloneChrome()
                                                           view.AddColumn("Culture", 120.0F)
                                                           view.AddColumn("Number", 170.0F)
                                                           view.AddColumn("Currency", 170.0F)
                                                           view.AddColumn("Percent", 140.0F)
                                                           view.AddColumn("Date", 160.0F)
                                                       End Sub))
            _formatRows.WithDefaultSize()

            _expansionRows = Own(_window.Controls.AddListView(configure:=Sub(view As MASListView)
                                                              view.WithDetailsView()
                                                              view.StandaloneChrome()
                                                              view.AddColumn("Key", 230.0F)
                                                              view.AddColumn("Target", 110.0F)
                                                              view.AddColumn("Ratio", 100.0F)
                                                              view.AddColumn("Layout pressure", 360.0F)
                                                          End Sub))
            _expansionRows.WithDefaultSize()

            _preview = Own(_window.Controls.AddLabel("Select a culture to see direction, sample text, formatting, and expansion pressure.",
                configure:=Sub(label As MASLabel)
                               label.LabelVariant = MASLabelVariant.Body
                               label.TextRole = MASLabelTextRole.Primary
                               label.MultiLine = True
                               label.WordWrap = True
                           End Sub))
            _preview.WithDefaultSize()

            _details = Own(_window.Controls.AddLabel("Select a culture row to see the product meaning of direction and mirrored layout facts.",
                configure:=Sub(label As MASLabel)
                               label.LabelVariant = MASLabelVariant.Body
                               label.TextRole = MASLabelTextRole.Secondary
                               label.MultiLine = True
                               label.WordWrap = True
                           End Sub))
            _details.WithDefaultSize()

            _ownership = Own(_window.Controls.AddLabel(
                "Boundary: LocalizationSystem owns the culture snapshot, string samples, format previews, expansion samples, and readiness proof. This page only displays those facts through MAS controls and MAS layout. Thread culture is never mutated. It does not mutate thread-culture state, mirror arbitrary host controls, or open a public translation API. No public translation API is opened.",
                configure:=Sub(label As MASLabel)
                               label.LabelVariant = MASLabelVariant.Caption
                               label.TextRole = MASLabelTextRole.Muted
                               label.MultiLine = True
                               label.WordWrap = True
                           End Sub))
            _ownership.WithDefaultSize()

            _refresh = Own(_window.Controls.AddButton("Refresh localization facts")).AsPrimary()
            _refresh.WithDefaultSize()
            AddHandler _refresh.Click, AddressOf HandleRefresh
        End Sub

        Private Sub LayoutControls()
            _window.Controls.LayoutPage(
                Sub(page As MASApplicationLayoutPageBuilder)
                    LayoutControls(page, includeHeader:=True)
                End Sub)
        End Sub

        Private Sub LayoutControls(page As MASApplicationLayoutPageBuilder, includeHeader As Boolean)
            If page Is Nothing Then Throw New ArgumentNullException(NameOf(page))

            Dim presentation As MASPresentationPageBuilder = MASPresentationPage.Begin(page, MASApplicationPageLayoutKind.Dashboard, _window.Shell)
            If includeHeader AndAlso _title IsNot Nothing Then
                presentation.Header(_title, _description)
            Else
                presentation.FullWidth(_description, MASSize.FillWidth)
            End If
            presentation.SectionIntro(_status, _summary)
            page.FilterBar(Sub(filters As MASApplicationFilterBarLayoutBuilder)
                               filters.AlignStart().HugContent().Field(_culturePickerLabel, _culturePicker, MASSize.Compact)
                           End Sub)
            presentation.FullWidth(_preview, MASSize.FillWidth)
            presentation.DataGridSurface(_cultureRows)
            presentation.DataGridSurface(_stringRows)
            presentation.DataGridSurface(_formatRows)
            presentation.DataGridSurface(_expansionRows)
            presentation.FullWidth(_details, MASSize.FillWidth)
            presentation.FullWidth(_ownership, MASSize.HugContent)
            presentation.Actions(
                Sub(actions As MASApplicationActionGroupLayoutBuilder)
                    actions.Gap(MASLayoutSpacing.Medium).AlignCenter()
                    actions.Add(_refresh, MASSize.[Default])
                End Sub)
        End Sub

        Private Sub HandleRefresh(sender As Object, e As EventArgs)
            RefreshLocalizationSafely(showDialogOnFailure:=True)
        End Sub

        Private Sub HandleCultureSelectionChanged(sender As Object, e As EventArgs)
            Try
                UpdatePreviewFromPicker()
            Catch ex As Exception
                ShowPageError("The selected localization culture could not be displayed.", ex)
            End Try
        End Sub

        Private Sub HandleCultureRowSelectionChanged(sender As Object, e As EventArgs)
            Try
                UpdateDetailsFromSelection()
            Catch ex As Exception
                ShowPageError("The selected localization row could not be displayed.", ex)
            End Try
        End Sub

        Private Sub RefreshLocalizationSafely(showDialogOnFailure As Boolean)
            Try
                RefreshLocalization()
            Catch ex As Exception
                SetUnavailableState("The localization page could not be refreshed.", ex)
                If showDialogOnFailure Then ShowPageError("The localization page could not be refreshed.", ex)
            End Try
        End Sub

        Private Sub RefreshLocalization()
            _snapshot = MASLocalization.CreateSnapshot()
            PopulateCulturePicker()
            PopulateCultureRows()
            PopulateStringRows()
            PopulateFormatRows()
            PopulateExpansionRows()
            UpdateSummary()
            SelectFirstCultureIfNeeded()
            UpdatePreviewFromPicker()
        End Sub

        Private Sub PopulateCulturePicker()
            If _culturePicker Is Nothing Then Return

            Dim labels As New List(Of String)()
            If _snapshot IsNot Nothing Then
                For Each culture As MASLocalizationCultureEntry In _snapshot.Cultures
                    If culture Is Nothing Then Continue For
                    labels.Add(culture.CultureName & " — " & culture.DisplayName)
                Next
            End If

            If labels.Count = 0 Then labels.Add("No culture facts")
            If labels.Count > MaxCatalogPreviewRows Then labels.RemoveRange(MaxCatalogPreviewRows, labels.Count - MaxCatalogPreviewRows)
            _culturePicker.SetItems(labels)
            _culturePicker.SelectedIndex = 0
        End Sub

        Private Sub PopulateCultureRows()
            If _cultureRows Is Nothing Then Return
            _cultureRows.ClearItems()
            If _snapshot Is Nothing Then Return

            Dim added As Integer = 0
            For Each culture As MASLocalizationCultureEntry In _snapshot.Cultures
                If added >= MaxCatalogPreviewRows Then Exit For
                If culture Is Nothing Then Continue For

                Dim item As MASListViewItem = MASListViewItem.Create(culture.CultureName).WithSubItems(New String() {
                    ResolveDirectionText(culture),
                    ResolveLayoutFlowText(culture),
                    culture.NativeName & " | decimal " & culture.DecimalSeparator & " | date " & culture.ShortDatePattern
                })
                item.Tag = culture
                _cultureRows.Add(item)
                added += 1
            Next
        End Sub

        Private Sub PopulateStringRows()
            If _stringRows Is Nothing Then Return
            _stringRows.ClearItems()
            If _snapshot Is Nothing Then Return

            Dim added As Integer = 0
            For Each entry As MASLocalizationStringEntry In _snapshot.LocalizedStrings
                If added >= MaxCatalogPreviewRows Then Exit For
                If entry Is Nothing Then Continue For
                _stringRows.Add(MASListViewItem.Create(entry.Key).WithSubItems(New String() {
                    entry.EnglishText,
                    entry.GermanText,
                    entry.ArabicText
                }))
                added += 1
            Next
        End Sub

        Private Sub PopulateFormatRows()
            If _formatRows Is Nothing Then Return
            _formatRows.ClearItems()
            If _snapshot Is Nothing Then Return

            Dim added As Integer = 0
            For Each sample As MASLocalizationFormatSample In _snapshot.FormatSamples
                If added >= MaxCatalogPreviewRows Then Exit For
                If sample Is Nothing Then Continue For
                _formatRows.Add(MASListViewItem.Create(sample.CultureName).WithSubItems(New String() {
                    sample.NumberSample,
                    sample.CurrencySample,
                    sample.PercentSample,
                    sample.DateSample
                }))
                added += 1
            Next
        End Sub

        Private Sub PopulateExpansionRows()
            If _expansionRows Is Nothing Then Return
            _expansionRows.ClearItems()
            If _snapshot Is Nothing Then Return

            Dim added As Integer = 0
            For Each sample As MASLocalizationExpansionSample In _snapshot.ExpansionSamples
                If added >= MaxCatalogPreviewRows Then Exit For
                If sample Is Nothing Then Continue For
                Dim pressure As String = If(sample.RequiresFlexibleLayout, "Flexible layout required", "Within compact text pressure")
                _expansionRows.Add(MASListViewItem.Create(sample.Key).WithSubItems(New String() {
                    sample.TargetCultureName,
                    sample.ExpansionRatio.ToString("0.00", CultureInfo.InvariantCulture) & "×",
                    pressure
                }))
                added += 1
            Next
        End Sub

        Private Sub UpdateSummary()
            If _snapshot Is Nothing Then
                SetUnavailableState("No localization snapshot is available.", Nothing)
                Return
            End If

            Dim readiness As String = If(_snapshot.ReadyForProductLayer, "product-layer ready", "partial facts available")
            _status.Text = "Localization / RTL status: " & readiness
            _summary.Text = "Cultures: " & _snapshot.CultureCount.ToString(CultureInfo.InvariantCulture) &
                " | Strings: " & _snapshot.LocalizedStringCount.ToString(CultureInfo.InvariantCulture) &
                " | Formats: " & _snapshot.FormatSampleCount.ToString(CultureInfo.InvariantCulture) &
                " | Expansion samples: " & _snapshot.ExpansionSampleCount.ToString(CultureInfo.InvariantCulture) &
                " | Bounded preview limit: " & MaxCatalogPreviewRows.ToString(CultureInfo.InvariantCulture) & " rows/catalog" &
                " | RTL: " & ResolveBool(_snapshot.HasRightToLeftCulture) &
                " | Mirrored layout: " & ResolveBool(_snapshot.HasMirroredLayoutCulture)
        End Sub

        Private Sub SelectFirstCultureIfNeeded()
            If _cultureRows IsNot Nothing AndAlso _snapshot IsNot Nothing AndAlso _snapshot.CultureCount > 0 Then
                _cultureRows.SelectedIndex = 0
            End If
        End Sub

        Private Sub UpdatePreviewFromPicker()
            Dim culture As MASLocalizationCultureEntry = ResolveSelectedCulture()
            If culture Is Nothing Then
                If _preview IsNot Nothing Then _preview.Text = "No selected culture is available."
                Return
            End If

            Dim sampleText As MASLocalizationStringEntry = ResolveFirstString()
            Dim format As MASLocalizationFormatSample = ResolveFormat(culture.CultureName)

            Dim localizedText As String = ResolveLocalizedText(sampleText, culture.CultureName)
            Dim formatText As String = If(format Is Nothing,
                                          "No format preview available.",
                                          "Number " & format.NumberSample & " | Currency " & format.CurrencySample & " | Percent " & format.PercentSample & " | Date " & format.DateSample)

            If _preview IsNot Nothing Then
                _preview.Text = culture.CultureName & " preview — " & ResolveDirectionText(culture) & ", " & ResolveLayoutFlowText(culture) & Environment.NewLine &
                    localizedText & Environment.NewLine &
                    formatText
            End If

            If _details IsNot Nothing Then
                _details.Text = BuildCultureDetails(culture)
            End If
        End Sub

        Private Sub UpdateDetailsFromSelection()
            If _cultureRows Is Nothing Then Return
            Dim item As MASListViewItem = _cultureRows.SelectedItem
            Dim culture As MASLocalizationCultureEntry = TryCast(If(item Is Nothing, Nothing, item.Tag), MASLocalizationCultureEntry)
            If culture Is Nothing Then Return
            If _details IsNot Nothing Then _details.Text = BuildCultureDetails(culture)
        End Sub

        Private Function ResolveSelectedCulture() As MASLocalizationCultureEntry
            If _snapshot Is Nothing OrElse _snapshot.CultureCount = 0 Then Return Nothing
            Dim index As Integer = If(_culturePicker Is Nothing, 0, _culturePicker.SelectedIndex)
            If index < 0 OrElse index >= _snapshot.CultureCount Then index = 0
            Return _snapshot.Cultures(index)
        End Function

        Private Function ResolveFirstString() As MASLocalizationStringEntry
            If _snapshot Is Nothing OrElse _snapshot.LocalizedStringCount = 0 Then Return Nothing
            Return _snapshot.LocalizedStrings(0)
        End Function

        Private Function ResolveFormat(cultureName As String) As MASLocalizationFormatSample
            If _snapshot Is Nothing Then Return Nothing
            For Each sample As MASLocalizationFormatSample In _snapshot.FormatSamples
                If sample IsNot Nothing AndAlso String.Equals(sample.CultureName, cultureName, StringComparison.OrdinalIgnoreCase) Then Return sample
            Next
            Return Nothing
        End Function

        Private Shared Function ResolveLocalizedText(entry As MASLocalizationStringEntry, cultureName As String) As String
            If entry Is Nothing Then Return String.Empty
            Return MASLocalization.ResolveText(entry.Key, cultureName, entry.EnglishText)
        End Function

        Private Shared Function BuildCultureDetails(culture As MASLocalizationCultureEntry) As String
            If culture Is Nothing Then Return "No selected culture details are available."
            Return culture.DisplayName & " uses " & ResolveDirectionText(culture) & " text and " & ResolveLayoutFlowText(culture) & ". " &
                "Nexamas UI exposes this as product-layer facts so consumers can prepare mirrored layout and expansion-safe pages through their own official layer."
        End Function

        Private Shared Function ResolveDirectionText(culture As MASLocalizationCultureEntry) As String
            If culture Is Nothing Then Return "Unknown"
            Return If(culture.IsRightToLeft, "Right-to-left", "Left-to-right")
        End Function

        Private Shared Function ResolveLayoutFlowText(culture As MASLocalizationCultureEntry) As String
            If culture Is Nothing Then Return "Unknown"
            Return If(culture.UsesMirroredLayout, "Mirrored", "Standard")
        End Function

        Private Shared Function ResolveBool(value As Boolean) As String
            Return If(value, "Yes", "No")
        End Function

        Private Sub SetUnavailableState(message As String, ex As Exception)
            If _status IsNot Nothing Then _status.Text = "Localization / RTL status: unavailable"
            If _summary IsNot Nothing Then _summary.Text = message & If(ex Is Nothing, String.Empty, " " & ex.Message)
            If _preview IsNot Nothing Then _preview.Text = "The host called MASLocalizationRtl.AttachPage only; Nexamas UI kept localization facts unavailable for this display."
            If _details IsNot Nothing Then _details.Text = "No localization details are available."
        End Sub

        Private Sub ShowPageError(message As String, ex As Exception)
            Try
                If _window IsNot Nothing AndAlso Not _window.IsDisposed AndAlso _window.Services IsNot Nothing Then
                    _window.Services.Dialogs.Error(message:=message,
                                                   title:="Nexamas UI Localization / RTL",
                                                   detail:=If(ex Is Nothing, String.Empty, ex.Message),
                                                   ownerKey:=DialogOwnerKey)
                End If
            Catch dialogException As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDiagnosticOnly(dialogException, "LocalizationRtl.Page.DialogBoundary")
            End Try
        End Sub
    End Class

End Namespace
