Option Strict On
Option Explicit On

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

Namespace Nexamas.UI.Controls

    ''' <summary>
    ''' Friend-owned visual policy for MASBadge. It keeps text hygiene, number overflow,
    ''' tone colors, text contrast, dot geometry, and disabled-state decisions inside the
    ''' badge surface without opening a public badge service or variant API.
    ''' </summary>
    Friend NotInheritable Class MASBadgeVisualPolicy
        Private Sub New()
        End Sub

        Friend Const MaxVisibleCharacters As Integer = 14
        Friend Const NumericOverflowText As String = "999+"

        Friend Shared Function NormalizeText(value As String) As String
            Dim text As String = If(value, String.Empty).Trim()
            If text.Length = 0 Then Return String.Empty
            text = CollapseInlineWhitespace(text)
            If text.Length > MaxVisibleCharacters Then text = text.Substring(0, MaxVisibleCharacters - 1) & "…"
            Return text
        End Function

        Friend Shared Function ResolveRenderText(text As String) As String
            Dim normalized As String = NormalizeText(text)
            If String.IsNullOrWhiteSpace(normalized) Then Return " "
            If IsNumericOverflow(normalized) Then Return NumericOverflowText
            Return normalized
        End Function

        Friend Shared Function ResolveTextStyle() As MASTypography.MASTextStyle
            Return MASTypography.MASTextStyle.Micro
        End Function

        Friend Shared Function BuildContentRect(bounds As SKRect,
                                                dpi As Single) As SKRect
            Return New SKRect(
                bounds.Left + BadgeTokens.PaddingHorizontalDip * dpi,
                bounds.Top + BadgeTokens.PaddingVerticalDip * dpi,
                bounds.Right - BadgeTokens.PaddingHorizontalDip * dpi,
                bounds.Bottom - BadgeTokens.PaddingVerticalDip * dpi)
        End Function

        Friend Shared Function BuildDotRect(bounds As SKRect,
                                            dpi As Single) As SKRect
            Dim size As Single = Math.Min(bounds.Width, bounds.Height)
            Dim diameter As Single = Math.Min(size, BadgeTokens.DotDiameterDip * dpi)
            If diameter <= 1.0F Then Return SKRect.Empty
            Return New SKRect(
                bounds.MidX - diameter / 2.0F,
                bounds.MidY - diameter / 2.0F,
                bounds.MidX + diameter / 2.0F,
                bounds.MidY + diameter / 2.0F)
        End Function

        Friend Shared Function ResolveToneColor(ctx As MASThemeContext,
                                                tone As MASToastTone) As SKColor
            If ctx Is Nothing Then Return SKColors.Gray

            Select Case tone
                Case MASToastTone.Success
                    If ctx.SemanticTheme IsNot Nothing Then Return ctx.SemanticTheme.Success
                Case MASToastTone.Warning
                    If ctx.SemanticTheme IsNot Nothing Then Return ctx.SemanticTheme.Warning
                Case MASToastTone.Danger
                    If ctx.SemanticTheme IsNot Nothing Then Return ctx.SemanticTheme.Danger
                Case MASToastTone.Info
                    If ctx.SemanticTheme IsNot Nothing Then Return ctx.SemanticTheme.Info
                Case Else
                    If ctx.BrandTheme IsNot Nothing Then Return ctx.BrandTheme.BrandPrimary
            End Select

            If ctx.SemanticTheme IsNot Nothing Then Return ctx.SemanticTheme.Info
            Return SKColors.Gray
        End Function

        Friend Shared Function ResolveEffectiveFillColor(ctx As MASThemeContext,
                                                         tone As MASToastTone,
                                                         enabled As Boolean) As SKColor
            Dim color As SKColor = ResolveToneColor(ctx, tone)
            If Not enabled Then color = color.WithAlpha(BadgeTokens.DisabledAlpha)
            Return color
        End Function

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

            If ctx IsNot Nothing AndAlso ctx.TextColorTheme IsNot Nothing Then Return ctx.TextColorTheme.InverseText
            Return SKColors.White
        End Function

        Friend Shared Function ResolveMinimumSize(dotOnly As Boolean) As SKSize
            If dotOnly Then Return New SKSize(BadgeTokens.DotMinSizeDip, BadgeTokens.DotMinSizeDip)
            Return New SKSize(BadgeTokens.MinWidthDip, BadgeTokens.MinHeightDip)
        End Function

        Friend Shared Function ResolveMinimumSize(textSize As SKSize,
                                                  dotOnly As Boolean) As SKSize
            If dotOnly Then Return ResolveMinimumSize(True)

            Return New SKSize(
                Math.Max(BadgeTokens.MinWidthDip,
                         BadgeTokens.PaddingHorizontalDip * 2.0F + SanitizeTextExtent(textSize.Width) + BadgeTokens.TextMeasureSafetyDip),
                BadgeTokens.MinHeightDip)
        End Function

        Friend Shared Function ResolveDesiredSize(textSize As SKSize,
                                                  dotOnly As Boolean) As SKSize
            If dotOnly Then Return ResolveMinimumSize(True)
            Return New SKSize(
                Math.Max(BadgeTokens.MinWidthDip,
                         BadgeTokens.PaddingHorizontalDip * 2.0F + SanitizeTextExtent(textSize.Width) + BadgeTokens.TextMeasureSafetyDip),
                Math.Max(BadgeTokens.MinHeightDip,
                         BadgeTokens.PaddingVerticalDip * 2.0F + SanitizeTextExtent(textSize.Height)))
        End Function

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

        Private Shared Function SanitizeTextExtent(value As Single) As Single
            If Single.IsNaN(value) OrElse Single.IsInfinity(value) OrElse value < 0.0F Then Return 0.0F
            Return value
        End Function

        Private Shared Function IsNumericOverflow(text As String) As Boolean
            If String.IsNullOrWhiteSpace(text) Then Return False
            Dim digits As String = text.Trim()
            If digits.Length <= 3 Then Return False
            For Each ch As Char In digits
                If Not Char.IsDigit(ch) Then Return False
            Next
            Return True
        End Function

        Private Shared Function IsLight(color As SKColor) As Boolean
            Dim luminance As Single = CSng((0.2126R * color.Red) + (0.7152R * color.Green) + (0.0722R * color.Blue))
            Return luminance >= 156.0F
        End Function

        Private Shared Function CollapseInlineWhitespace(value As String) As String
            Dim text As String = If(value, String.Empty)
            If text.Length = 0 Then Return String.Empty

            Dim chars As New System.Text.StringBuilder(text.Length)
            Dim inWhitespace As Boolean = False
            For Each ch As Char In text
                If Char.IsWhiteSpace(ch) Then
                    If Not inWhitespace Then chars.Append(" "c)
                    inWhitespace = True
                Else
                    chars.Append(ch)
                    inWhitespace = False
                End If
            Next
            Return chars.ToString().Trim()
        End Function
    End Class

End Namespace
