Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports Nexamas.UI.Diagnostics
Imports Nexamas.UI.Localization

Namespace Nexamas.UI.Quality

    ''' <summary>
    ''' Proves LOC-06: unsupported or invalid RTL runtime-culture resolution does not fall back to LTR silently.
    ''' </summary>
    Friend NotInheritable Class MASLocalizationSilentRtlFallbackDiagnosticsGate
        Private Sub New()
        End Sub

        Friend Shared Function Passes() As Boolean
            Return ProbeUnsupportedRtlCultureFallbackIsDiagnosticVisible() AndAlso
                   ProbeInvalidCultureFallbackIncludesReason()
        End Function

        Private Shared Function ProbeUnsupportedRtlCultureFallbackIsDiagnosticVisible() As Boolean
            Dim previousSnapshot As MASLocalizationRuntimeEnvironmentSnapshot = MASLocalization.GetRuntimeEnvironmentSnapshot()
            Try
                MASRuntimeFaultChannel.ResetForTests()
                MASLocalization.ResetRtlResolutionDiagnosticsForTests()

                Dim snapshot As MASLocalizationRuntimeEnvironmentSnapshot =
                    MASLocalization.SetRuntimeCulture("ar-SA", "LocalizationSilentRtlFallbackDiagnosticsGate.UnsupportedRtl")
                Dim report As MASLocalizationRtlResolutionDiagnosticReport = MASLocalization.GetRtlResolutionDiagnosticsReport()
                Dim faults As IReadOnlyList(Of MASRuntimeFaultRecord) = MASRuntimeFaultChannel.GetRecentFaultsSnapshot()

                Return snapshot IsNot Nothing AndAlso
                       report IsNot Nothing AndAlso
                       String.Equals(snapshot.CultureName, "en-US", StringComparison.OrdinalIgnoreCase) AndAlso
                       Not snapshot.IsRightToLeft AndAlso
                       report.FallbackCount > 0 AndAlso
                       String.Equals(report.LastDiagnosticCode, "UnsupportedRtlCultureFallback", StringComparison.OrdinalIgnoreCase) AndAlso
                       String.Equals(report.LastRequestedCultureName, "ar-SA", StringComparison.OrdinalIgnoreCase) AndAlso
                       String.Equals(report.LastFallbackCultureName, "en-US", StringComparison.OrdinalIgnoreCase) AndAlso
                       report.LastReason.IndexOf("right-to-left", StringComparison.OrdinalIgnoreCase) >= 0 AndAlso
                       ContainsRtlFallbackFault(faults, "UnsupportedRtlCultureFallback", "ar-SA", "en-US")
            Catch ex As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDiagnosticOnly(ex, "MASLocalizationSilentRtlFallbackDiagnosticsGate.UnsupportedRtl")
                Return False
            Finally
                RestoreRuntimeSnapshot(previousSnapshot, "LocalizationSilentRtlFallbackDiagnosticsGate.UnsupportedRtl.Restore")
            End Try
        End Function

        Private Shared Function ProbeInvalidCultureFallbackIncludesReason() As Boolean
            Dim previousSnapshot As MASLocalizationRuntimeEnvironmentSnapshot = MASLocalization.GetRuntimeEnvironmentSnapshot()
            Try
                MASRuntimeFaultChannel.ResetForTests()
                MASLocalization.ResetRtlResolutionDiagnosticsForTests()

                Dim snapshot As MASLocalizationRuntimeEnvironmentSnapshot =
                    MASLocalization.SetRuntimeCulture("invalid culture name!!", "LocalizationSilentRtlFallbackDiagnosticsGate.InvalidCulture")
                Dim report As MASLocalizationRtlResolutionDiagnosticReport = MASLocalization.GetRtlResolutionDiagnosticsReport()

                Return snapshot IsNot Nothing AndAlso
                       report IsNot Nothing AndAlso
                       String.Equals(snapshot.CultureName, "en-US", StringComparison.OrdinalIgnoreCase) AndAlso
                       Not snapshot.IsRightToLeft AndAlso
                       report.FallbackCount > 0 AndAlso
                       String.Equals(report.LastDiagnosticCode, "InvalidCultureFallback", StringComparison.OrdinalIgnoreCase) AndAlso
                       report.LastRequestedCultureName.IndexOf("invalid culture", StringComparison.OrdinalIgnoreCase) >= 0 AndAlso
                       report.LastReason.IndexOf("CultureInfo", StringComparison.OrdinalIgnoreCase) >= 0 AndAlso
                       report.LastReason.IndexOf("silent False RTL fact", StringComparison.OrdinalIgnoreCase) >= 0
            Catch ex As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDiagnosticOnly(ex, "MASLocalizationSilentRtlFallbackDiagnosticsGate.InvalidCulture")
                Return False
            Finally
                RestoreRuntimeSnapshot(previousSnapshot, "LocalizationSilentRtlFallbackDiagnosticsGate.InvalidCulture.Restore")
            End Try
        End Function

        Private Shared Function ContainsRtlFallbackFault(faults As IReadOnlyList(Of MASRuntimeFaultRecord),
                                                         code As String,
                                                         requestedCulture As String,
                                                         fallbackCulture As String) As Boolean
            If faults Is Nothing Then Return False

            For Each record As MASRuntimeFaultRecord In faults
                If record Is Nothing Then Continue For

                If record.Context.IndexOf("Localization.RtlResolutionFallback." & code, StringComparison.OrdinalIgnoreCase) >= 0 AndAlso
                   record.Message.IndexOf("RequestedCulture=" & requestedCulture, StringComparison.OrdinalIgnoreCase) >= 0 AndAlso
                   record.Message.IndexOf("FallbackCulture=" & fallbackCulture, StringComparison.OrdinalIgnoreCase) >= 0 AndAlso
                   record.ExceptionTypeName.IndexOf("MASLocalizationRtlResolutionFallback", StringComparison.OrdinalIgnoreCase) >= 0 Then
                    Return True
                End If
            Next

            Return False
        End Function

        Private Shared Sub RestoreRuntimeSnapshot(previousSnapshot As MASLocalizationRuntimeEnvironmentSnapshot,
                                                  reason As String)
            Try
                If previousSnapshot IsNot Nothing AndAlso
                   String.Equals(previousSnapshot.Source, "ExplicitRuntimeCulture", StringComparison.Ordinal) Then
                    MASLocalization.SetRuntimeCulture(previousSnapshot.CultureName, reason)
                Else
                    MASLocalization.UseCurrentThreadCulture(reason)
                End If
            Catch ex As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDiagnosticOnly(ex, "MASLocalizationSilentRtlFallbackDiagnosticsGate.Restore")
            End Try
        End Sub
    End Class

End Namespace
