Option Strict On
Option Explicit On

Imports System
Imports System.Globalization
Imports System.Windows.Forms

Namespace Nexamas.UI.Localization

    ''' <summary>
    ''' Internal contract result that keeps UI layout direction and content text direction as separate facts.
    ''' </summary>
    Friend NotInheritable Class MASLocalizationDirectionContractResolution
        Friend Sub New(uiCultureName As String,
                       uiTextDirection As MASLocalizationTextDirection,
                       uiLayoutFlow As MASLocalizationLayoutFlow,
                       contentTextDirection As MASLocalizationTextDirection,
                       mirrorsHorizontalKeyboardNavigation As Boolean,
                       mirrorsTabOrder As Boolean)
            Me.UiCultureName = Normalize(uiCultureName)
            Me.UiTextDirection = uiTextDirection
            Me.UiLayoutFlow = uiLayoutFlow
            Me.ContentTextDirection = contentTextDirection
            Me.MirrorsHorizontalKeyboardNavigation = mirrorsHorizontalKeyboardNavigation
            Me.MirrorsTabOrder = mirrorsTabOrder
        End Sub

        Friend ReadOnly Property UiCultureName As String
        Friend ReadOnly Property UiTextDirection As MASLocalizationTextDirection
        Friend ReadOnly Property UiLayoutFlow As MASLocalizationLayoutFlow
        Friend ReadOnly Property ContentTextDirection As MASLocalizationTextDirection
        Friend ReadOnly Property MirrorsHorizontalKeyboardNavigation As Boolean
        Friend ReadOnly Property MirrorsTabOrder As Boolean

        Friend ReadOnly Property SeparatesUiLayoutFromContentTextDirection As Boolean
            Get
                Return (UiLayoutFlow = MASLocalizationLayoutFlow.Mirrored AndAlso ContentTextDirection = MASLocalizationTextDirection.LeftToRight) OrElse
                       (UiLayoutFlow = MASLocalizationLayoutFlow.Standard AndAlso ContentTextDirection = MASLocalizationTextDirection.RightToLeft) OrElse
                       (UiTextDirection = ContentTextDirection)
            End Get
        End Property

        Private Shared Function Normalize(value As String) As String
            Return If(value, String.Empty).Trim()
        End Function
    End Class

    ''' <summary>
    ''' Logical keyboard intent used by RTL-aware controls without exposing a new public API surface.
    ''' </summary>
    Friend Enum MASLocalizationKeyboardNavigationIntent
        None = 0
        PreviousLogicalItem = 1
        NextLogicalItem = 2
    End Enum

    ''' <summary>
    ''' Friend-owned Localization/RTL contract for residual review: UI layout mirroring is derived from
    ''' product culture, while content text direction is resolved from the string itself. Keyboard navigation
    ''' mirrors horizontal arrow semantics in mirrored UI layout, but tab order remains logical for accessibility.
    ''' </summary>
    Friend NotInheritable Class MASLocalizationDirectionContract
        Private Sub New()
        End Sub

        Friend Shared Function Resolve(uiCultureName As String,
                                       contentText As String) As MASLocalizationDirectionContractResolution
            Dim culture As MASLocalizationCultureEntry = MASLocalizationCultureCatalog.ResolveCulture(uiCultureName)
            Dim uiTextDirection As MASLocalizationTextDirection = If(culture Is Nothing,
                                                                      MASLocalizationTextDirection.LeftToRight,
                                                                      culture.TextDirection)
            Dim uiLayoutFlow As MASLocalizationLayoutFlow = If(culture Is Nothing,
                                                                MASLocalizationLayoutFlow.Standard,
                                                                culture.LayoutFlow)
            Dim contentDirection As MASLocalizationTextDirection = ResolveContentTextDirection(contentText, uiTextDirection)

            Return New MASLocalizationDirectionContractResolution(
                uiCultureName:=If(culture Is Nothing, "en-US", culture.CultureName),
                uiTextDirection:=uiTextDirection,
                uiLayoutFlow:=uiLayoutFlow,
                contentTextDirection:=contentDirection,
                mirrorsHorizontalKeyboardNavigation:=MirrorsHorizontalKeyboardNavigation(uiLayoutFlow),
                mirrorsTabOrder:=MirrorsTabOrder(uiLayoutFlow))
        End Function

        Friend Shared Function ResolveContentTextDirection(contentText As String,
                                                          fallbackDirection As MASLocalizationTextDirection) As MASLocalizationTextDirection
            Dim text As String = If(contentText, String.Empty)
            If ContainsStrongRtl(text) Then Return MASLocalizationTextDirection.RightToLeft
            If ContainsStrongLtr(text) Then Return MASLocalizationTextDirection.LeftToRight
            Return fallbackDirection
        End Function

        Friend Shared Function MirrorsHorizontalKeyboardNavigation(layoutFlow As MASLocalizationLayoutFlow) As Boolean
            Return layoutFlow = MASLocalizationLayoutFlow.Mirrored
        End Function

        Friend Shared Function MirrorsTabOrder(layoutFlow As MASLocalizationLayoutFlow) As Boolean
            Return False
        End Function

        Friend Shared Function ResolveHorizontalNavigation(layoutFlow As MASLocalizationLayoutFlow,
                                                          keyCode As Keys) As MASLocalizationKeyboardNavigationIntent
            Dim mirrored As Boolean = MirrorsHorizontalKeyboardNavigation(layoutFlow)

            Select Case keyCode
                Case Keys.Left
                    Return If(mirrored,
                              MASLocalizationKeyboardNavigationIntent.NextLogicalItem,
                              MASLocalizationKeyboardNavigationIntent.PreviousLogicalItem)
                Case Keys.Right
                    Return If(mirrored,
                              MASLocalizationKeyboardNavigationIntent.PreviousLogicalItem,
                              MASLocalizationKeyboardNavigationIntent.NextLogicalItem)
                Case Else
                    Return MASLocalizationKeyboardNavigationIntent.None
            End Select
        End Function

        Private Shared Function ContainsStrongRtl(text As String) As Boolean
            If String.IsNullOrEmpty(text) Then Return False

            For i As Integer = 0 To text.Length - 1
                Dim code As Integer = AscW(text(i)) And &HFFFF
                If IsStrongRtlCodePoint(code) Then Return True
            Next

            Return False
        End Function

        Private Shared Function ContainsStrongLtr(text As String) As Boolean
            If String.IsNullOrEmpty(text) Then Return False

            For i As Integer = 0 To text.Length - 1
                Dim ch As Char = text(i)
                Dim code As Integer = AscW(ch) And &HFFFF
                If IsStrongLtrCodePoint(code) Then Return True
            Next

            Return False
        End Function

        Private Shared Function IsStrongRtlCodePoint(code As Integer) As Boolean
            Return (code >= &H590 AndAlso code <= &H5FF) OrElse
                   (code >= &H600 AndAlso code <= &H6FF) OrElse
                   (code >= &H750 AndAlso code <= &H77F) OrElse
                   (code >= &H8A0 AndAlso code <= &H8FF) OrElse
                   (code >= &HFB50 AndAlso code <= &HFDFF) OrElse
                   (code >= &HFE70 AndAlso code <= &HFEFF)
        End Function

        Private Shared Function IsStrongLtrCodePoint(code As Integer) As Boolean
            Return (code >= &H41 AndAlso code <= &H5A) OrElse
                   (code >= &H61 AndAlso code <= &H7A) OrElse
                   (code >= &HC0 AndAlso code <= &H2AF) OrElse
                   (code >= &H370 AndAlso code <= &H52F)
        End Function
    End Class

End Namespace
