Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports Nexamas.UI.Icons
Imports Nexamas.UI.TextRendering
Imports Nexamas.UI.TextInput
Imports Nexamas.UI.Theming
Imports SkiaSharp

Namespace Nexamas.UI.Controls

    ''' <summary>
    ''' Friend-only presentation policy for MASValidationMessage. Rule execution
    ''' remains owned by FormValidationSystem and inline validation indicators
    ''' remain owned by TextInput controls. This policy owns only product-facing
    ''' message hygiene, semantic icon/tone mapping, wrapping, and readiness facts.
    ''' </summary>
    Friend NotInheritable Class MASValidationMessagePolicy

        Friend Const MaxWrappedWidthDip As Single = 420.0F
        Friend Const MaxWrappedLines As Integer = 3

        Private Sub New()
        End Sub

        Friend Shared Function NormalizeMessageText(value As String) As String
            Dim s As String = If(value, String.Empty)
            s = s.Replace(vbCrLf, vbLf)
            s = s.Replace(vbCr, vbLf)

            Dim rawLines As String() = s.Split(New String() {vbLf}, StringSplitOptions.None)
            Dim result As New StringBuilder(s.Length)

            For Each rawLine As String In rawLines
                Dim line As String = CollapseSpaces(If(rawLine, String.Empty)).Trim()
                If line.Length = 0 Then Continue For

                If result.Length > 0 Then result.Append(vbLf)
                result.Append(line)
            Next

            Return result.ToString()
        End Function

        Friend Shared Function NormalizeState(value As MASTextValidationState) As MASTextValidationState
            Select Case value
                Case MASTextValidationState.None,
                     MASTextValidationState.Information,
                     MASTextValidationState.Success,
                     MASTextValidationState.Warning,
                     MASTextValidationState.Error
                    Return value
                Case Else
                    Return MASTextValidationState.Information
            End Select
        End Function

        Friend Shared Function ResolveIconKind(state As MASTextValidationState) As MASIconKind
            Select Case NormalizeState(state)
                Case MASTextValidationState.Success
                    Return MASIconKind.Success
                Case MASTextValidationState.Warning
                    Return MASIconKind.Warning
                Case MASTextValidationState.Error
                    Return MASIconKind.Failure
                Case Else
                    Return MASIconKind.Info
            End Select
        End Function

        Friend Shared Function ResolveStateColor(ctx As MASThemeContext,
                                                 state As MASTextValidationState) As SKColor
            If ctx Is Nothing OrElse ctx.SemanticTheme Is Nothing Then Return SKColors.Transparent

            Select Case NormalizeState(state)
                Case MASTextValidationState.Success
                    Return ctx.SemanticTheme.Success
                Case MASTextValidationState.Warning
                    Return ctx.SemanticTheme.Warning
                Case MASTextValidationState.Error
                    Return ctx.SemanticTheme.Danger
                Case MASTextValidationState.Information
                    Return ctx.SemanticTheme.Info
                Case Else
                    Return ResolveMutedColor(ctx)
            End Select
        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
            End If
            Return Nexamas.UI.Values.Color.Text.Muted
        End Function

        Friend Shared Function BuildWrappedLines(text As String,
                                                 paint As SKPaint,
                                                 maxWidthPx As Single,
                                                 maxLines As Integer) As List(Of String)
            Dim result As New List(Of String)()
            Dim s As String = NormalizeMessageText(text)
            If s.Length = 0 OrElse paint Is Nothing Then Return result

            Dim safeWidth As Single = Math.Max(12.0F, maxWidthPx)
            Dim safeMaxLines As Integer = Math.Max(1, maxLines)
            Dim explicitLines As String() = s.Split(New String() {vbLf}, StringSplitOptions.None)

            For Each explicitLine As String In explicitLines
                AddWrappedLine(result, explicitLine, paint, safeWidth, safeMaxLines)
                If result.Count >= safeMaxLines Then Exit For
            Next

            If result.Count > safeMaxLines Then
                result.RemoveRange(safeMaxLines, result.Count - safeMaxLines)
            End If

            If result.Count = safeMaxLines AndAlso s.Length > 0 Then
                result(result.Count - 1) = FitLastLine(result(result.Count - 1), paint, safeWidth)
            End If

            Return result
        End Function

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

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

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

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

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

        Private Shared Sub AddWrappedLine(result As List(Of String),
                                          line As String,
                                          paint As SKPaint,
                                          maxWidthPx As Single,
                                          maxLines As Integer)
            If result Is Nothing OrElse paint Is Nothing Then Return
            If result.Count >= maxLines Then Return

            Dim cleanLine As String = CollapseSpaces(If(line, String.Empty)).Trim()
            If cleanLine.Length = 0 Then Return

            Dim words As String() = cleanLine.Split(New Char() {" "c}, StringSplitOptions.RemoveEmptyEntries)
            Dim current As String = String.Empty

            For Each word As String In words
                Dim candidate As String = If(current.Length = 0, word, current & " " & word)
                If MASShapedText.MeasureWidth(candidate, paint) <= maxWidthPx OrElse current.Length = 0 Then
                    current = candidate
                Else
                    result.Add(current)
                    If result.Count >= maxLines Then Return
                    current = word
                End If
            Next

            If current.Length > 0 AndAlso result.Count < maxLines Then
                result.Add(current)
            End If
        End Sub

        Private Shared Function FitLastLine(value As String,
                                            paint As SKPaint,
                                            maxWidthPx As Single) As String
            Dim s As String = If(value, String.Empty)
            If s.Length = 0 OrElse paint Is Nothing Then Return s
            If MASShapedText.MeasureWidth(s, paint) <= maxWidthPx Then Return s
            Return Nexamas.UI.MASTextCore.FitEllipsis(s, maxWidthPx, paint)
        End Function

        Private Shared Function CollapseSpaces(value As String) As String
            If String.IsNullOrEmpty(value) Then Return String.Empty

            Dim result As New StringBuilder(value.Length)
            Dim previousWasSpace As Boolean
            For Each ch As Char In value
                If ch = ControlChars.Lf Then
                    result.Append(ch)
                    previousWasSpace = False
                    Continue For
                End If

                Dim isSpace As Boolean = Char.IsWhiteSpace(ch)
                If isSpace Then
                    If Not previousWasSpace Then result.Append(" "c)
                    previousWasSpace = True
                Else
                    result.Append(ch)
                    previousWasSpace = False
                End If
            Next

            Return result.ToString()
        End Function

    End Class

End Namespace
