Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports Nexamas.UI.Components.ListPopup
Imports Nexamas.UI.Rendering
Imports Nexamas.UI.General

Imports Nexamas.UI.Values
Imports SkiaSharp

Namespace Nexamas.UI.Components

    ''' <summary>
    ''' Friend-owned policy for AvatarGroup overflow presentation.  It turns the +N
    ''' chip into an actionable people-summary popover without introducing a people
    ''' directory, profile editor, image store, or application-owned navigation route.
    ''' </summary>
    Friend NotInheritable Class MASAvatarOverflowPopoverPolicy
        Private Sub New()
        End Sub

        Friend Shared Function NormalizeHiddenStartIndex(visibleAvatarCount As Integer,
                                                        avatarCount As Integer) As Integer
            Dim total As Integer = Math.Max(0, avatarCount)
            If total <= 0 Then Return 0
            Dim visible As Integer = Math.Max(0, Math.Min(visibleAvatarCount, total))
            Return visible
        End Function

        Friend Shared Function CreateOverflowItems(avatars As IReadOnlyList(Of MASAvatar),
                                                   visibleAvatarCount As Integer) As List(Of MASAvatarOverflowItem)
            Dim result As New List(Of MASAvatarOverflowItem)()
            If avatars Is Nothing Then Return result

            Dim startIndex As Integer = NormalizeHiddenStartIndex(visibleAvatarCount, avatars.Count)
            For i As Integer = startIndex To avatars.Count - 1
                Dim avatar As MASAvatar = avatars(i)
                If avatar Is Nothing Then Continue For
                result.Add(MASAvatarOverflowItem.FromAvatar(i, avatar))
            Next

            Return result
        End Function

        Friend Shared Function MeasurePopupSizePx(itemCount As Integer,
                                                  dpi As Single) As SKSize
            dpi = PixelSnap.SafeDpi(dpi)
            Dim count As Integer = Math.Max(0, itemCount)
            Dim rows As Integer = ResolveVisibleRows(count)
            Dim width As Single = AvatarTokens.OverflowPopupWidthDip * dpi
            Dim height As Single = (AvatarTokens.OverflowPopupPaddingDip * 2.0F +
                                    AvatarTokens.OverflowPopupHeaderHeightDip +
                                    AvatarTokens.OverflowPopupHeaderGapDip +
                                    Math.Max(1, rows) * AvatarTokens.OverflowPopupRowHeightDip) * dpi
            Return New SKSize(Math.Max(1.0F, width), Math.Max(1.0F, height))
        End Function

        Friend Shared Function ResolvePopupBoundsPx(anchorPx As SKRect,
                                                    itemCount As Integer,
                                                    dpi As Single,
                                                    surfaceSizeProvider As Func(Of SKSizeI)) As SKRect
            dpi = PixelSnap.SafeDpi(dpi)
            Dim popupSize As SKSize = MeasurePopupSizePx(itemCount, dpi)
            Return DropDownPositionPolicy.Calculate(
                anchor:=anchorPx,
                overlaySize:=popupSize,
                dpi:=dpi,
                gapPx:=AvatarTokens.OverflowPopupGapDip * dpi,
                surfaceSizeProvider:=surfaceSizeProvider)
        End Function

        Friend Shared Function ResolveVisibleRows(itemCount As Integer) As Integer
            If itemCount <= 0 Then Return 1
            Return Math.Max(1, Math.Min(itemCount, AvatarTokens.OverflowPopupMaxVisibleRows))
        End Function

        Friend Shared Function ResolveMaxScrollOffset(itemCount As Integer) As Integer
            Return Math.Max(0, itemCount - ResolveVisibleRows(itemCount))
        End Function

        Friend Shared Function NormalizeScrollOffset(value As Integer,
                                                     itemCount As Integer) As Integer
            Dim maxOffset As Integer = ResolveMaxScrollOffset(itemCount)
            If value < 0 Then Return 0
            If value > maxOffset Then Return maxOffset
            Return value
        End Function

        Friend Shared Function ContainsOverflowVisualPoint(overflowRectPx As SKRect,
                                                           ptPx As SKPoint,
                                                           dpi As Single) As Boolean
            Return MASAvatarIdentityPolicy.ContainsAvatarVisualPoint(overflowRectPx, ptPx, dpi)
        End Function

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

        Friend Shared Function HasNoProfileEditorRoute() As Boolean
            Return True
        End Function
    End Class

    Friend NotInheritable Class MASAvatarOverflowItem
        Friend Sub New(sourceIndex As Integer,
                       displayName As String,
                       initials As String,
                       accentColor As SKColor,
                       presenceText As String,
                       showPresence As Boolean)
            Me.SourceIndex = Math.Max(0, sourceIndex)
            Me.DisplayName = MASAvatarIdentityPolicy.NormalizeDisplayName(displayName)
            Me.Initials = MASAvatarIdentityPolicy.ResolveInitials(Me.DisplayName, initials)
            Me.AccentColor = accentColor
            Me.PresenceText = MASAvatarIdentityPolicy.NormalizePresence(presenceText)
            Me.ShowPresence = showPresence
        End Sub

        Friend ReadOnly Property SourceIndex As Integer
        Friend ReadOnly Property DisplayName As String
        Friend ReadOnly Property Initials As String
        Friend ReadOnly Property AccentColor As SKColor
        Friend ReadOnly Property PresenceText As String
        Friend ReadOnly Property ShowPresence As Boolean

        Friend Shared Function FromAvatar(sourceIndex As Integer,
                                          avatar As MASAvatar) As MASAvatarOverflowItem
            If avatar Is Nothing Then
                Return New MASAvatarOverflowItem(sourceIndex, String.Empty, AvatarTokens.DefaultInitials, New SKColor(54, 104, 224), String.Empty, False)
            End If

            Return New MASAvatarOverflowItem(
                sourceIndex:=sourceIndex,
                displayName:=avatar.DisplayName,
                initials:=avatar.Initials,
                accentColor:=avatar.AccentColor,
                presenceText:=avatar.PresenceText,
                showPresence:=avatar.ShowPresence)
        End Function
    End Class

End Namespace
