Option Strict On
Option Explicit On

Imports System
Imports System.Globalization
Imports SkiaSharp
Imports Nexamas.UI.Rendering
Imports Nexamas.UI.Theming
Imports Nexamas.UI.General
Imports Nexamas.UI.Values

Namespace Nexamas.UI.Components

    ''' <summary>
    ''' Friend-owned identity visual policy for MASAvatar. It centralizes display-name
    ''' hygiene, Unicode-safe initials, deterministic fallback colors, presence tone mapping,
    ''' and RTL/presence geometry without introducing an image loader, people directory, or
    ''' public presence service.
    ''' </summary>
    Friend NotInheritable Class MASAvatarIdentityPolicy
        Private Sub New()
        End Sub

        Friend Shared Function NormalizeDisplayName(value As String) As String
            Dim text As String = If(value, String.Empty).Trim()
            If text.Length > AvatarTokens.MaxDisplayNameLength Then text = text.Substring(0, AvatarTokens.MaxDisplayNameLength)
            Return text
        End Function

        Friend Shared Function NormalizePresence(value As String) As String
            Dim text As String = If(value, String.Empty).Trim().ToLowerInvariant()
            If text.Length > 32 Then text = text.Substring(0, 32)
            Return text
        End Function

        Friend Shared Function ResolveInitials(displayName As String,
                                               explicitInitials As String) As String
            Dim text As String = If(explicitInitials, String.Empty).Trim()
            If text.Length = 0 Then text = BuildInitialsFromName(displayName)
            If text.Length = 0 Then text = AvatarTokens.DefaultInitials
            text = LimitTextElements(text, AvatarTokens.MaxInitialsLength)
            Return text.ToUpper(CultureInfo.CurrentUICulture)
        End Function

        Friend Shared Function ResolveDeterministicAccent(displayName As String,
                                                          fallback As SKColor) As SKColor
            Dim text As String = NormalizeDisplayName(displayName)
            If text.Length = 0 Then Return fallback

            Dim palette As SKColor() = {
                New SKColor(54, 104, 224),
                New SKColor(14, 165, 233),
                New SKColor(16, 185, 129),
                New SKColor(245, 158, 11),
                New SKColor(236, 72, 153),
                New SKColor(139, 92, 246),
                New SKColor(239, 68, 68),
                New SKColor(20, 184, 166)
            }

            Dim hash As ULong = 2166136261UL
            For Each ch As Char In text.ToUpperInvariant()
                hash = ((hash Xor CULng(Convert.ToUInt16(ch))) * 16777619UL) And &HFFFFFFFFUL
            Next

            Dim index As Integer = CInt(hash Mod CULng(palette.Length))
            Return palette(index)
        End Function

        Friend Shared Function ResolvePresenceColor(ctx As MASThemeContext,
                                                    presenceText As String) As SKColor
            Select Case NormalizePresence(presenceText)
                Case AvatarTokens.OnlinePresence
                    If ctx IsNot Nothing AndAlso ctx.SemanticTheme IsNot Nothing Then Return ctx.SemanticTheme.Success
                    Return New SKColor(34, 197, 94)
                Case AvatarTokens.BusyPresence
                    If ctx IsNot Nothing AndAlso ctx.SemanticTheme IsNot Nothing Then Return ctx.SemanticTheme.Danger
                    Return New SKColor(239, 68, 68)
                Case AvatarTokens.AwayPresence
                    If ctx IsNot Nothing AndAlso ctx.SemanticTheme IsNot Nothing Then Return ctx.SemanticTheme.Warning
                    Return New SKColor(245, 158, 11)
                Case Else
                    Return ResolveMutedColor(ctx)
            End Select
        End Function

        Friend Shared Function ResolvePresenceCenter(bounds As SKRect,
                                                     dpi As Single,
                                                     isRtl As Boolean) As SKPoint
            Dim size As Single = ResolvePresenceDiameter(bounds, dpi)
            Dim x As Single = If(isRtl, bounds.Left + size * 0.45F, bounds.Right - size * 0.45F)
            Return New SKPoint(x, bounds.Bottom - size * 0.45F)
        End Function

        Friend Shared Function ResolvePresenceDiameter(bounds As SKRect,
                                                       dpi As Single) As Single
            Return Math.Max(7.0F * dpi, Math.Min(bounds.Width, bounds.Height) * AvatarTokens.PresenceSizeRatio)
        End Function

        Friend Shared Function ContainsAvatarVisualPoint(bounds As SKRect,
                                                         ptPx As SKPoint,
                                                         dpi As Single) As Boolean
            If bounds.Width <= 1.0F OrElse bounds.Height <= 1.0F Then Return False

            Dim safeDpi As Single = PixelSnap.SafeDpi(dpi)
            Dim snapped As SKRect = PixelSnap.SnapRect(bounds, safeDpi)
            Dim radius As Single = Math.Min(snapped.Width, snapped.Height) / 2.0F + AvatarTokens.VisualHitSlopDip * safeDpi
            Dim dx As Single = ptPx.X - snapped.MidX
            Dim dy As Single = ptPx.Y - snapped.MidY
            Return dx * dx + dy * dy <= radius * radius
        End Function

        Friend Shared Function HasCircularVisualHitTestingPolicy() As Boolean
            Return True
        End Function

        Friend Shared Function ResolveSurfaceColor(ctx As MASThemeContext) As SKColor
            If ctx IsNot Nothing AndAlso ctx.SurfaceTheme IsNot Nothing Then Return ctx.SurfaceTheme.SurfaceMid
            Return New SKColor(255, 255, 255)
        End Function

        Friend Shared Function ResolveTextColor(ctx As MASThemeContext) As SKColor
            If ctx IsNot Nothing AndAlso ctx.TextColorTheme IsNot Nothing Then Return ctx.TextColorTheme.PrimaryText
            Return Nexamas.UI.Values.Color.Text.Primary
        End Function

        Friend Shared Function ResolveMutedColor(ctx As MASThemeContext) As SKColor
            If ctx IsNot Nothing AndAlso ctx.TextColorTheme IsNot Nothing Then Return ctx.TextColorTheme.MutedText
            Return SKColors.Gray
        End Function

        Friend Shared Function ResolveAccentColor(ctx As MASThemeContext) As SKColor
            If ctx IsNot Nothing AndAlso ctx.BrandTheme IsNot Nothing Then Return ctx.BrandTheme.BrandPrimary
            If ctx IsNot Nothing AndAlso ctx.SemanticTheme IsNot Nothing Then Return ctx.SemanticTheme.Info
            Return SKColors.DodgerBlue
        End Function

        Friend Shared Function ResolveRingColor(ctx As MASThemeContext) As SKColor
            If ctx IsNot Nothing AndAlso ctx.SurfaceTheme IsNot Nothing Then Return ctx.SurfaceTheme.SurfaceTop
            Return SKColors.White
        End Function

        Friend Shared Function BuildReadinessManifest() As MASAvatarReadinessManifest
            Return MASAvatarReadinessManifest.Ready()
        End Function

        Private Shared Function BuildInitialsFromName(displayName As String) As String
            Dim name As String = NormalizeDisplayName(displayName)
            If name.Length = 0 Then Return String.Empty

            Dim parts As String() = name.Split(New Char() {" "c, "-"c, "_"c, "."c}, StringSplitOptions.RemoveEmptyEntries)
            If parts.Length = 0 Then Return FirstTextElement(name)

            Dim result As String = String.Empty
            For Each part As String In parts
                If part.Length = 0 Then Continue For
                result &= FirstTextElement(part)
                If CountTextElements(result) >= 2 Then Exit For
            Next
            Return result
        End Function

        Private Shared Function FirstTextElement(value As String) As String
            If String.IsNullOrEmpty(value) Then Return String.Empty
            Dim iterator As TextElementEnumerator = StringInfo.GetTextElementEnumerator(value)
            If iterator.MoveNext() Then Return CStr(iterator.GetTextElement())
            Return String.Empty
        End Function

        Private Shared Function LimitTextElements(value As String,
                                                  maxElements As Integer) As String
            If String.IsNullOrEmpty(value) OrElse maxElements <= 0 Then Return String.Empty
            Dim iterator As TextElementEnumerator = StringInfo.GetTextElementEnumerator(value)
            Dim result As String = String.Empty
            Dim count As Integer = 0
            While iterator.MoveNext() AndAlso count < maxElements
                result &= CStr(iterator.GetTextElement())
                count += 1
            End While
            Return result
        End Function

        Private Shared Function CountTextElements(value As String) As Integer
            If String.IsNullOrEmpty(value) Then Return 0
            Return New StringInfo(value).LengthInTextElements
        End Function
    End Class

End Namespace
