Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports Nexamas.UI.Icons
Imports Nexamas.UI.Theming
Imports Nexamas.UI.TextRendering
Imports Nexamas.UI.Values
Imports SkiaSharp

Namespace Nexamas.UI.Controls

    ''' <summary>
    ''' Friend-only content and illustration policy for MASEmptyState. It owns empty-state
    ''' text hygiene, fallback copy, wrapped text lines, compact text placement, RTL text
    ''' detection, theme color resolution, and the official MASIconKind illustration choice.
    ''' Data/search/file/list adapters, page state machines, action commands, and loading
    ''' handoff remain owned by their existing Nexamas UI systems.
    ''' </summary>
    Friend NotInheritable Class MASEmptyStateContentPolicy

        Friend Const MaxTitleLines As Integer = 2
        Friend Const MaxDescriptionLines As Integer = 3
        Private Const EllipsisText As String = "…"

        Private Sub New()
        End Sub

        Friend Shared Function NormalizeText(value As String) As String
            If value Is Nothing Then Return String.Empty
            Return value.Trim()
        End Function

        Friend Shared Function ResolveTitleText(value As String) As String
            Dim normalized As String = NormalizeText(value)
            If Not String.IsNullOrWhiteSpace(normalized) Then Return normalized
            Return "Nothing here yet"
        End Function

        Friend Shared Function ResolveDescriptionText(value As String) As String
            Dim normalized As String = NormalizeText(value)
            If Not String.IsNullOrWhiteSpace(normalized) Then Return normalized
            Return "Content will appear here when it is available."
        End Function

        Friend Shared Function ResolveIllustrationKind() As MASIconKind
            Return MASIconKind.Search
        End Function

        Friend Shared Function ResolveTextIsRtl(titleText As String,
                                                descriptionText As String) As Boolean
            Return ContainsRtlText(titleText) OrElse ContainsRtlText(descriptionText)
        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 New SKColor(70, 128, 220, 255)
        End Function

        Friend Shared Function ResolveTitleColor(ctx As MASThemeContext) As SKColor
            If ctx IsNot Nothing AndAlso ctx.TextColorTheme IsNot Nothing Then
                Return ctx.TextColorTheme.PrimaryText.WithAlpha(EmptyStateTokens.TitleTextAlpha)
            End If

            Return Nexamas.UI.Values.Color.Text.Primary.WithAlpha(EmptyStateTokens.TitleTextAlpha)
        End Function

        Friend Shared Function ResolveDescriptionColor(ctx As MASThemeContext) As SKColor
            If ctx IsNot Nothing AndAlso ctx.TextColorTheme IsNot Nothing Then
                Return ctx.TextColorTheme.SecondaryText.WithAlpha(EmptyStateTokens.DescriptionTextAlpha)
            End If

            Return Nexamas.UI.Values.Color.Text.Secondary.WithAlpha(EmptyStateTokens.DescriptionTextAlpha)
        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)()
            If paint Is Nothing Then Return result

            Dim source As String = ResolveSafeText(text)
            Dim limit As Integer = Math.Max(1, maxLines)
            Dim width As Single = If(Single.IsNaN(maxWidthPx) OrElse Single.IsInfinity(maxWidthPx), Single.PositiveInfinity, Math.Max(1.0F, maxWidthPx))

            If String.IsNullOrWhiteSpace(source) Then
                result.Add(String.Empty)
                Return result
            End If

            Dim words As String() = source.Split(New Char() {" "c, ControlChars.Tab}, StringSplitOptions.RemoveEmptyEntries)
            If words.Length = 0 Then
                result.Add(source)
                Return result
            End If

            Dim line As String = String.Empty
            For Each word As String In words
                Dim candidate As String = If(String.IsNullOrEmpty(line), word, line & " " & word)
                If MASTextLayoutMeasurementGateway.MeasureShapedWidth(candidate, paint) <= width OrElse String.IsNullOrEmpty(line) Then
                    line = candidate
                Else
                    result.Add(line)
                    If result.Count >= limit Then Exit For
                    line = word
                End If
            Next

            If result.Count < limit AndAlso Not String.IsNullOrEmpty(line) Then result.Add(line)
            If result.Count = 0 Then result.Add(source)

            If result.Count >= limit Then
                Dim lastIndex As Integer = result.Count - 1
                result(lastIndex) = EllipsizeToWidth(result(lastIndex), paint, width)
            End If

            Return result
        End Function

        Friend Shared Function BuildContentPlan(content As SKRect,
                                                dpi As Single,
                                                showIllustration As Boolean,
                                                titleLineCount As Integer,
                                                descriptionLineCount As Integer) As MASEmptyStateContentPlan
            Dim safeDpi As Single = Nexamas.UI.General.PixelSnap.SafeDpi(dpi)
            Dim safeTitleLines As Integer = Math.Max(1, titleLineCount)
            Dim safeDescriptionLines As Integer = Math.Max(1, descriptionLineCount)
            Dim illustrationHeight As Single = If(showIllustration, EmptyStateTokens.IllustrationDiameterDip * safeDpi, 0.0F)
            Dim illustrationGap As Single = If(showIllustration, EmptyStateTokens.IllustrationTextGapDip * safeDpi, 0.0F)
            Dim titleLineHeight As Single = EmptyStateTokens.TitleLineHeightDip * safeDpi
            Dim descriptionLineHeight As Single = EmptyStateTokens.DescriptionLineHeightDip * safeDpi
            Dim gap As Single = EmptyStateTokens.TitleDescriptionGapDip * safeDpi
            Dim totalHeight As Single = illustrationHeight + illustrationGap + titleLineHeight * safeTitleLines + gap + descriptionLineHeight * safeDescriptionLines
            Dim top As Single = content.MidY - totalHeight / 2.0F
            Dim illustrationRect As SKRect = SKRect.Empty

            If showIllustration Then
                Dim illustrationSize As Single = Math.Min(EmptyStateTokens.IllustrationDiameterDip * safeDpi, Math.Min(content.Width, content.Height))
                illustrationRect = New SKRect(
                    content.MidX - illustrationSize / 2.0F,
                    top,
                    content.MidX + illustrationSize / 2.0F,
                    top + illustrationSize)
                top = illustrationRect.Bottom + EmptyStateTokens.IllustrationTextGapDip * safeDpi
            End If

            Dim textWidth As Single = Math.Min(content.Width, EmptyStateTokens.MaxTextWidthDip * safeDpi)
            Dim textLeft As Single = content.MidX - textWidth / 2.0F
            Dim textRight As Single = content.MidX + textWidth / 2.0F
            Dim titleRect As New SKRect(textLeft, top, textRight, top + titleLineHeight * safeTitleLines)
            Dim descriptionRect As New SKRect(textLeft, titleRect.Bottom + gap, textRight, titleRect.Bottom + gap + descriptionLineHeight * safeDescriptionLines)

            Return New MASEmptyStateContentPlan(illustrationRect, titleRect, descriptionRect, titleLineHeight, descriptionLineHeight, showIllustration)
        End Function

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

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

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

        Private Shared Function ResolveSafeText(value As String) As String
            Dim normalized As String = NormalizeText(value)
            If String.IsNullOrEmpty(normalized) Then Return String.Empty
            Return normalized.Replace(ControlChars.Cr, " ").Replace(ControlChars.Lf, " ").Replace(ControlChars.Tab, " ")
        End Function

        Private Shared Function EllipsizeToWidth(value As String,
                                                 paint As SKPaint,
                                                 maxWidthPx As Single) As String
            If paint Is Nothing OrElse String.IsNullOrEmpty(value) Then Return value
            Return MASTextLayoutMeasurementGateway.FitEllipsisShaped(value, maxWidthPx, paint)
        End Function

        Private Shared Function ContainsRtlText(value As String) As Boolean
            If String.IsNullOrEmpty(value) Then Return False

            For Each ch As Char In value
                Dim code As Integer = AscW(ch)
                If (code >= &H590 AndAlso code <= &H8FF) OrElse
                   (code >= &HFB1D AndAlso code <= &HFDFF) OrElse
                   (code >= &HFE70 AndAlso code <= &HFEFF) Then
                    Return True
                End If
            Next

            Return False
        End Function

    End Class

    Friend NotInheritable Class MASEmptyStateContentPlan
        Friend Sub New(illustrationRect As SKRect,
                       titleRect As SKRect,
                       descriptionRect As SKRect,
                       titleLineHeightPx As Single,
                       descriptionLineHeightPx As Single,
                       hasIllustration As Boolean)
            Me.IllustrationRect = illustrationRect
            Me.TitleRect = titleRect
            Me.DescriptionRect = descriptionRect
            Me.TitleLineHeightPx = Math.Max(1.0F, titleLineHeightPx)
            Me.DescriptionLineHeightPx = Math.Max(1.0F, descriptionLineHeightPx)
            Me.HasIllustration = hasIllustration
        End Sub

        Friend ReadOnly Property IllustrationRect As SKRect
        Friend ReadOnly Property TitleRect As SKRect
        Friend ReadOnly Property DescriptionRect As SKRect
        Friend ReadOnly Property TitleLineHeightPx As Single
        Friend ReadOnly Property DescriptionLineHeightPx As Single
        Friend ReadOnly Property HasIllustration As Boolean
    End Class

End Namespace
