Option Strict On
Option Explicit On

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

Namespace Nexamas.UI.Controls

    ''' <summary>
    ''' Friend-only visual policy for MASLoadingSkeleton. It owns row/line normalization,
    ''' variant geometry, deterministic line widths, theme color resolution, and the stable
    ''' reduced-motion rendering contract. Data loading, progress lifetime, clock-based activity, motion
    ''' clocks, virtualization, and render/performance runners remain outside the control.
    ''' </summary>
    Friend NotInheritable Class MASLoadingSkeletonVisualPolicy

        Private Sub New()
        End Sub

        Friend Shared Function NormalizeRowCount(value As Integer) As Integer
            If value < LoadingSkeletonTokens.MinRows Then Return LoadingSkeletonTokens.MinRows
            If value > LoadingSkeletonTokens.MaxRows Then Return LoadingSkeletonTokens.MaxRows
            Return value
        End Function

        Friend Shared Function NormalizeLineCount(value As Integer) As Integer
            If value < LoadingSkeletonTokens.MinLines Then Return LoadingSkeletonTokens.MinLines
            If value > LoadingSkeletonTokens.MaxLines Then Return LoadingSkeletonTokens.MaxLines
            Return value
        End Function

        Friend Shared Function ResolveRowHeightDip(blockMode As Boolean,
                                                   avatarVisible As Boolean,
                                                   lineCount As Integer) As Single
            If blockMode Then Return LoadingSkeletonTokens.BlockHeightDip
            Dim safeLineCount As Integer = NormalizeLineCount(lineCount)
            Dim lineTotal As Single = CSng(safeLineCount) * LoadingSkeletonTokens.LineHeightDip + CSng(Math.Max(0, safeLineCount - 1)) * LoadingSkeletonTokens.LineGapDip
            If avatarVisible Then Return Math.Max(LoadingSkeletonTokens.AvatarDiameterDip, lineTotal)
            Return Math.Max(LoadingSkeletonTokens.RowHeightDip, lineTotal)
        End Function

        Friend Shared Function BuildLayoutPlan(content As SKRect,
                                               rowCount As Integer,
                                               lineCount As Integer,
                                               blockMode As Boolean,
                                               avatarVisible As Boolean,
                                               dpi As Single) As MASLoadingSkeletonLayoutPlan
            Dim safeDpi As Single = Nexamas.UI.General.PixelSnap.SafeDpi(dpi)
            Dim safeRows As Integer = NormalizeRowCount(rowCount)
            Dim rowHeight As Single = ResolveRowHeightDip(blockMode, avatarVisible, lineCount) * safeDpi
            Dim rowGap As Single = LoadingSkeletonTokens.RowGapDip * safeDpi
            Dim rows As New List(Of SKRect)()
            Dim y As Single = content.Top

            For index As Integer = 0 To safeRows - 1
                If y >= content.Bottom Then Exit For
                Dim rowRect As New SKRect(content.Left, y, content.Right, Math.Min(content.Bottom, y + rowHeight))
                If rowRect.Width > 1.0F AndAlso rowRect.Height > 1.0F Then rows.Add(rowRect)
                y += rowHeight + rowGap
            Next

            Return New MASLoadingSkeletonLayoutPlan(rows.ToArray(), rowHeight, rowGap)
        End Function

        Friend Shared Function ResolveLineWidthRatio(rowIndex As Integer,
                                                     lineIndex As Integer,
                                                     lineCount As Integer) As Single
            Dim pattern As Integer = Math.Abs((rowIndex * 3 + lineIndex) Mod 5)
            Dim ratio As Single
            Select Case pattern
                Case 0
                    ratio = 0.92F
                Case 1
                    ratio = 0.74F
                Case 2
                    ratio = 0.58F
                Case 3
                    ratio = 0.84F
                Case Else
                    ratio = 0.66F
            End Select

            If NormalizeLineCount(lineCount) > 1 AndAlso lineIndex = NormalizeLineCount(lineCount) - 1 Then ratio = Math.Min(ratio, 0.62F)
            Return Math.Max(0.24F, Math.Min(0.96F, ratio))
        End Function

        Friend Shared Function ResolveBaseColor(ctx As MASThemeContext) As SKColor
            If ctx IsNot Nothing AndAlso ctx.TextColorTheme IsNot Nothing Then
                Return ctx.TextColorTheme.SecondaryText
            End If

            Return New SKColor(LoadingSkeletonTokens.FallbackGray,
                               LoadingSkeletonTokens.FallbackGray,
                               LoadingSkeletonTokens.FallbackGray,
                               255)
        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 HasReducedMotionStableRenderPolicy() As Boolean
            Return True
        End Function

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

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

    End Class

    Friend NotInheritable Class MASLoadingSkeletonLayoutPlan
        Friend Sub New(rowRects As SKRect(),
                       rowHeightPx As Single,
                       rowGapPx As Single)
            Me.RowRects = If(rowRects, Array.Empty(Of SKRect)())
            Me.RowHeightPx = Math.Max(1.0F, rowHeightPx)
            Me.RowGapPx = Math.Max(0.0F, rowGapPx)
        End Sub

        Friend ReadOnly Property RowRects As SKRect()
        Friend ReadOnly Property RowHeightPx As Single
        Friend ReadOnly Property RowGapPx As Single
    End Class

End Namespace
