Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports System.Globalization
Imports System.Windows.Forms
Imports Nexamas.UI.FloatRuntime
Imports Nexamas.UI.General
Imports Nexamas.UI.Rendering
Imports Nexamas.UI.TextRendering
Imports Nexamas.UI.Theming
Imports Nexamas.UI.Values
Imports SkiaSharp

Namespace Nexamas.UI.Components

    ''' <summary>
    ''' Internal FloatRuntime content for AvatarGroup overflow.  It is a compact people
    ''' summary only: selecting a row invokes the owning AvatarGroup callback while profile
    ''' navigation, account editing, image upload, persistence, and permission decisions stay
    ''' with the host application.
    ''' </summary>
    Friend Partial NotInheritable Class MASAvatarOverflowFloatContent
        Implements IMASFloatContent
        Implements IMASFloatInputPolicy
        Implements IMASFloatRenderableContent
        Implements IMASFloatRoutedInputContent

        Private ReadOnly _items As List(Of MASAvatarOverflowItem)
        Private ReadOnly _onItemInvoked As Action(Of Integer)
        Private _session As IMASFloatSession
        Private _boundsPx As SKRect = SKRect.Empty
        Private _rowsAreaPx As SKRect = SKRect.Empty
        Private _scrollOffset As Integer
        Private _hoverRow As Integer = -1
        Private _pressedRow As Integer = -1

        Friend Sub New(items As IEnumerable(Of MASAvatarOverflowItem),
                       onItemInvoked As Action(Of Integer))
            _items = New List(Of MASAvatarOverflowItem)()
            If items IsNot Nothing Then
                For Each item As MASAvatarOverflowItem In items
                    If item IsNot Nothing Then _items.Add(item)
                Next
            End If
            _onItemInvoked = onItemInvoked
        End Sub

        Public ReadOnly Property Name As String Implements IMASFloatContent.Name
            Get
                Return AvatarTokens.OverflowPopupContentName
            End Get
        End Property

        Public ReadOnly Property AcceptsPointerInput As Boolean Implements IMASFloatInputPolicy.AcceptsPointerInput
            Get
                Return True
            End Get
        End Property

        Public ReadOnly Property AcceptsKeyboardInput As Boolean Implements IMASFloatInputPolicy.AcceptsKeyboardInput
            Get
                Return True
            End Get
        End Property

        Public ReadOnly Property AcceptsTextInput As Boolean Implements IMASFloatInputPolicy.AcceptsTextInput
            Get
                Return False
            End Get
        End Property

        Public ReadOnly Property CloseOnOutsidePointer As Boolean Implements IMASFloatInputPolicy.CloseOnOutsidePointer
            Get
                Return True
            End Get
        End Property

        Public ReadOnly Property SwallowOutsidePointer As Boolean Implements IMASFloatInputPolicy.SwallowOutsidePointer
            Get
                Return True
            End Get
        End Property

        Public ReadOnly Property CloseOnEscape As Boolean Implements IMASFloatInputPolicy.CloseOnEscape
            Get
                Return True
            End Get
        End Property

        Public Sub AttachSession(session As IMASFloatSession) Implements IMASFloatContent.AttachSession
            _session = session
        End Sub

        Public Sub DetachSession() Implements IMASFloatContent.DetachSession
            StopAvatarOverflowContentMotion(resetState:=True)
            _session = Nothing
            _hoverRow = -1
            _pressedRow = -1
        End Sub

        Public Sub RenderFloat(canvas As SKCanvas,
                               ctx As MASThemeContext,
                               boundsPx As SKRect) Implements IMASFloatRenderableContent.RenderFloat
            If canvas Is Nothing OrElse ctx Is Nothing Then Return
            If boundsPx.Width <= 1.0F OrElse boundsPx.Height <= 1.0F Then Return

            Dim dpi As Single = PixelSnap.SafeDpi(ctx.Dpi)
            _boundsPx = PixelSnap.SnapRect(boundsPx, dpi)
            Dim radius As Single = AvatarTokens.OverflowPopupRadiusDip * dpi

            DrawSurface(canvas, ctx, _boundsPx, radius, dpi)
            DrawHeader(canvas, ctx, _boundsPx, dpi)
            DrawRows(canvas, ctx, _boundsPx, dpi)
        End Sub

        Private Sub DrawSurface(canvas As SKCanvas,
                                ctx As MASThemeContext,
                                bounds As SKRect,
                                radius As Single,
                                dpi As Single)
            Dim surfaceColor As SKColor = MASAvatarIdentityPolicy.ResolveSurfaceColor(ctx)
            Using fill As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = surfaceColor.WithAlpha(AvatarTokens.OverflowPopupSurfaceAlpha)}
                canvas.DrawRoundRect(bounds, radius, radius, fill)
            End Using

            Using stroke As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Stroke, .StrokeWidth = Math.Max(1.0F, AvatarTokens.OverflowPopupStrokeDip * dpi), .Color = MASAvatarIdentityPolicy.ResolveRingColor(ctx).WithAlpha(AvatarTokens.OverflowPopupStrokeAlpha)}
                canvas.DrawRoundRect(bounds, radius, radius, stroke)
            End Using
        End Sub

        Private Sub DrawHeader(canvas As SKCanvas,
                               ctx As MASThemeContext,
                               bounds As SKRect,
                               dpi As Single)
            Dim pad As Single = AvatarTokens.OverflowPopupPaddingDip * dpi
            Dim headerHeight As Single = AvatarTokens.OverflowPopupHeaderHeightDip * dpi
            Dim header As New SKRect(bounds.Left + pad, bounds.Top + pad, bounds.Right - pad, bounds.Top + pad + headerHeight)
            Dim isRtl As Boolean = ResolveRightToLeft()
            Dim title As String = AvatarTokens.OverflowPopupTitle
            Dim countText As String = _items.Count.ToString(CultureInfo.InvariantCulture)

            TypographyTextPrimitives.DrawSingleLineText(
                canvas:=canvas,
                ctx:=ctx,
                text:=title,
                bounds:=header,
                dpi:=dpi,
                style:=MASTypography.MASTextStyle.Small,
                color:=MASAvatarIdentityPolicy.ResolveTextColor(ctx).WithAlpha(AvatarTokens.TextAlpha),
                align:=If(isRtl, TypographyTextPrimitives.TextAlign.Right, TypographyTextPrimitives.TextAlign.Left),
                drawShadow:=False)

            TypographyTextPrimitives.DrawSingleLineText(
                canvas:=canvas,
                ctx:=ctx,
                text:=countText,
                bounds:=header,
                dpi:=dpi,
                style:=MASTypography.MASTextStyle.Small,
                color:=MASAvatarIdentityPolicy.ResolveMutedColor(ctx).WithAlpha(AvatarTokens.MutedTextAlpha),
                align:=If(isRtl, TypographyTextPrimitives.TextAlign.Left, TypographyTextPrimitives.TextAlign.Right),
                drawShadow:=False)
        End Sub

        Private Sub DrawRows(canvas As SKCanvas,
                             ctx As MASThemeContext,
                             bounds As SKRect,
                             dpi As Single)
            Dim pad As Single = AvatarTokens.OverflowPopupPaddingDip * dpi
            Dim headerHeight As Single = AvatarTokens.OverflowPopupHeaderHeightDip * dpi
            Dim headerGap As Single = AvatarTokens.OverflowPopupHeaderGapDip * dpi
            Dim rowHeight As Single = AvatarTokens.OverflowPopupRowHeightDip * dpi
            Dim visibleRows As Integer = MASAvatarOverflowPopoverPolicy.ResolveVisibleRows(_items.Count)

            _rowsAreaPx = PixelSnap.SnapRect(New SKRect(bounds.Left + pad, bounds.Top + pad + headerHeight + headerGap, bounds.Right - pad, bounds.Top + pad + headerHeight + headerGap + visibleRows * rowHeight), dpi)

            Dim saveCount As Integer = canvas.Save()
            canvas.ClipRect(_rowsAreaPx, SKClipOperation.Intersect, True)

            For visibleRow As Integer = 0 To visibleRows - 1
                Dim sourceRow As Integer = _scrollOffset + visibleRow
                If sourceRow < 0 OrElse sourceRow >= _items.Count Then Exit For

                Dim row As New SKRect(_rowsAreaPx.Left, _rowsAreaPx.Top + visibleRow * rowHeight, _rowsAreaPx.Right, _rowsAreaPx.Top + (visibleRow + 1) * rowHeight)
                DrawRow(canvas, ctx, row, dpi, sourceRow)
            Next

            DrawAvatarOverflowContentMotionOverlay(canvas, ctx, dpi)

            canvas.RestoreToCount(saveCount)

            If MASAvatarOverflowPopoverPolicy.ResolveMaxScrollOffset(_items.Count) > 0 Then
                DrawScrollHint(canvas, ctx, bounds, dpi)
            End If
        End Sub

        Private Sub DrawRow(canvas As SKCanvas,
                            ctx As MASThemeContext,
                            row As SKRect,
                            dpi As Single,
                            sourceRow As Integer)
            If sourceRow < 0 OrElse sourceRow >= _items.Count Then Return

            Dim item As MASAvatarOverflowItem = _items(sourceRow)
            Dim rowRadius As Single = AvatarTokens.OverflowPopupRowRadiusDip * dpi
            Dim isPressed As Boolean = (sourceRow = _pressedRow)
            Dim isHovered As Boolean = (sourceRow = _hoverRow)
            If isPressed OrElse isHovered Then
                Dim alpha As Byte = If(isPressed, AvatarTokens.PressedAlpha, AvatarTokens.HoverAlpha)
                Using hover As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = MASAvatarIdentityPolicy.ResolveAccentColor(ctx).WithAlpha(alpha)}
                    canvas.DrawRoundRect(PixelSnap.SnapRect(row, dpi), rowRadius, rowRadius, hover)
                End Using
            End If

            Dim isRtl As Boolean = ResolveRightToLeft()
            Dim avatarSize As Single = AvatarTokens.OverflowPopupAvatarSizeDip * dpi
            Dim avatarLeft As Single = If(isRtl, row.Right - AvatarTokens.OverflowPopupRowPaddingDip * dpi - avatarSize, row.Left + AvatarTokens.OverflowPopupRowPaddingDip * dpi)
            Dim avatarTop As Single = row.MidY - avatarSize / 2.0F
            Dim avatarRect As New SKRect(avatarLeft, avatarTop, avatarLeft + avatarSize, avatarTop + avatarSize)
            DrawMiniAvatar(canvas, ctx, avatarRect, dpi, item)

            Dim textLeft As Single
            Dim textRight As Single
            If isRtl Then
                textLeft = row.Left + AvatarTokens.OverflowPopupRowPaddingDip * dpi
                textRight = avatarRect.Left - AvatarTokens.OverflowPopupTextGapDip * dpi
            Else
                textLeft = avatarRect.Right + AvatarTokens.OverflowPopupTextGapDip * dpi
                textRight = row.Right - AvatarTokens.OverflowPopupRowPaddingDip * dpi
            End If

            Dim primary As New SKRect(textLeft, row.Top + 4.0F * dpi, textRight, row.MidY + 1.0F * dpi)
            Dim secondary As New SKRect(textLeft, row.MidY - 1.0F * dpi, textRight, row.Bottom - 3.0F * dpi)
            Dim nameText As String = If(String.IsNullOrWhiteSpace(item.DisplayName), item.Initials, item.DisplayName)
            Dim detailText As String = ResolveDetailText(item)

            TypographyTextPrimitives.DrawSingleLineText(
                canvas:=canvas,
                ctx:=ctx,
                text:=nameText,
                bounds:=primary,
                dpi:=dpi,
                style:=MASTypography.MASTextStyle.Small,
                color:=MASAvatarIdentityPolicy.ResolveTextColor(ctx).WithAlpha(AvatarTokens.TextAlpha),
                align:=If(isRtl, TypographyTextPrimitives.TextAlign.Right, TypographyTextPrimitives.TextAlign.Left),
                drawShadow:=False)

            TypographyTextPrimitives.DrawSingleLineText(
                canvas:=canvas,
                ctx:=ctx,
                text:=detailText,
                bounds:=secondary,
                dpi:=dpi,
                style:=MASTypography.MASTextStyle.Small,
                color:=MASAvatarIdentityPolicy.ResolveMutedColor(ctx).WithAlpha(AvatarTokens.MutedTextAlpha),
                align:=If(isRtl, TypographyTextPrimitives.TextAlign.Right, TypographyTextPrimitives.TextAlign.Left),
                drawShadow:=False)
        End Sub

        Private Sub DrawMiniAvatar(canvas As SKCanvas,
                                   ctx As MASThemeContext,
                                   bounds As SKRect,
                                   dpi As Single,
                                   item As MASAvatarOverflowItem)
            Dim snapped As SKRect = PixelSnap.SnapRect(bounds, dpi)
            Dim topColor As SKColor = ColorMath.Mix(item.AccentColor, SKColors.White, 0.28F).WithAlpha(AvatarTokens.FillTopAlpha)
            Dim bottomColor As SKColor = ColorMath.Mix(item.AccentColor, SKColors.Black, 0.18F).WithAlpha(AvatarTokens.FillBottomAlpha)

            Using shader As SKShader = SKShader.CreateLinearGradient(New SKPoint(snapped.Left, snapped.Top), New SKPoint(snapped.Left, snapped.Bottom), New SKColor() {topColor, bottomColor}, Nothing, SKShaderTileMode.Clamp)
                Using fill As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Shader = shader}
                    canvas.DrawOval(snapped, fill)
                End Using
            End Using

            Using stroke As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Stroke, .StrokeWidth = Math.Max(1.0F, AvatarTokens.RingStrokeDip * dpi), .Color = MASAvatarIdentityPolicy.ResolveRingColor(ctx).WithAlpha(AvatarTokens.RingAlpha)}
                canvas.DrawOval(snapped, stroke)
            End Using

            TypographyTextPrimitives.DrawSingleLineText(
                canvas:=canvas,
                ctx:=ctx,
                text:=item.Initials,
                bounds:=snapped,
                dpi:=dpi,
                style:=MASTypography.MASTextStyle.Small,
                color:=MASAvatarIdentityPolicy.ResolveTextColor(ctx).WithAlpha(AvatarTokens.TextAlpha),
                align:=TypographyTextPrimitives.TextAlign.Center,
                drawShadow:=False)

            If item.ShowPresence Then
                Dim presenceSize As Single = Math.Max(6.0F * dpi, snapped.Width * AvatarTokens.PresenceSizeRatio)
                Dim center As New SKPoint(snapped.Right - presenceSize * 0.45F, snapped.Bottom - presenceSize * 0.45F)
                Using borderPaint As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = MASAvatarIdentityPolicy.ResolveSurfaceColor(ctx)}
                    canvas.DrawCircle(center, presenceSize / 2.0F + AvatarTokens.PresenceBorderDip * dpi, borderPaint)
                End Using
                Using fillPaint As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = MASAvatarIdentityPolicy.ResolvePresenceColor(ctx, item.PresenceText)}
                    canvas.DrawCircle(center, presenceSize / 2.0F, fillPaint)
                End Using
            End If
        End Sub

        Private Sub DrawScrollHint(canvas As SKCanvas,
                                   ctx As MASThemeContext,
                                   bounds As SKRect,
                                   dpi As Single)
            Dim trackWidth As Single = Math.Max(2.0F, AvatarTokens.OverflowPopupScrollTrackWidthDip * dpi)
            Dim pad As Single = AvatarTokens.OverflowPopupPaddingDip * dpi
            Dim track As New SKRect(bounds.Right - pad * 0.5F - trackWidth, _rowsAreaPx.Top, bounds.Right - pad * 0.5F, _rowsAreaPx.Bottom)
            Dim total As Integer = Math.Max(1, _items.Count)
            Dim visible As Integer = MASAvatarOverflowPopoverPolicy.ResolveVisibleRows(_items.Count)
            Dim thumbHeight As Single = Math.Max(AvatarTokens.OverflowPopupScrollMinThumbDip * dpi, track.Height * (CSng(visible) / CSng(total)))
            Dim maxOffset As Integer = MASAvatarOverflowPopoverPolicy.ResolveMaxScrollOffset(_items.Count)
            Dim travel As Single = Math.Max(0.0F, track.Height - thumbHeight)
            Dim top As Single = track.Top + If(maxOffset <= 0, 0.0F, travel * (CSng(_scrollOffset) / CSng(maxOffset)))
            Dim thumb As New SKRect(track.Left, top, track.Right, top + thumbHeight)

            Using paint As New SKPaint With {.IsAntialias = True, .Style = SKPaintStyle.Fill, .Color = MASAvatarIdentityPolicy.ResolveMutedColor(ctx).WithAlpha(AvatarTokens.OverflowPopupScrollAlpha)}
                canvas.DrawRoundRect(thumb, trackWidth / 2.0F, trackWidth / 2.0F, paint)
            End Using
        End Sub

        Public Function HitTestFloat(ctx As MASThemeContext,
                                     boundsPx As SKRect,
                                     ptPx As SKPoint) As Boolean Implements IMASFloatRoutedInputContent.HitTestFloat
            Return boundsPx.Contains(ptPx.X, ptPx.Y)
        End Function

        Public Sub PointerMoveFloat(ctx As MASThemeContext,
                                    ptPx As SKPoint) Implements IMASFloatRoutedInputContent.PointerMoveFloat
            Dim nextRow As Integer = HitRow(ptPx)
            If nextRow = _hoverRow Then Return
            _hoverRow = nextRow
            StartAvatarOverflowContentMotion(nextRow)
            RequestInvalidate()
        End Sub

        Public Function PointerDownFloat(ctx As MASThemeContext,
                                         ptPx As SKPoint,
                                         button As MouseButtons) As Boolean Implements IMASFloatRoutedInputContent.PointerDownFloat
            If button <> MouseButtons.Left Then Return False
            _pressedRow = HitRow(ptPx)
            _hoverRow = _pressedRow
            StartAvatarOverflowContentMotion(_pressedRow)
            RequestInvalidate()
            Return _pressedRow >= 0
        End Function

        Public Function PointerUpFloat(ctx As MASThemeContext,
                                       ptPx As SKPoint,
                                       button As MouseButtons) As Boolean Implements IMASFloatRoutedInputContent.PointerUpFloat
            If button <> MouseButtons.Left Then Return False
            Dim pressed As Integer = _pressedRow
            Dim released As Integer = HitRow(ptPx)
            _pressedRow = -1
            _hoverRow = released
            StartAvatarOverflowContentMotion(released)

            If pressed >= 0 AndAlso pressed = released AndAlso pressed < _items.Count Then
                InvokeItem(_items(pressed).SourceIndex)
                Return True
            End If

            RequestInvalidate()
            Return pressed >= 0 OrElse released >= 0
        End Function

        Public Function PointerWheelFloat(ctx As MASThemeContext,
                                          ptPx As SKPoint,
                                          delta As Integer) As Boolean Implements IMASFloatRoutedInputContent.PointerWheelFloat
            If Not _rowsAreaPx.Contains(ptPx.X, ptPx.Y) Then Return False
            Dim stepDelta As Integer = If(delta < 0, 1, -1)
            Dim nextOffset As Integer = MASAvatarOverflowPopoverPolicy.NormalizeScrollOffset(_scrollOffset + stepDelta, _items.Count)
            If nextOffset = _scrollOffset Then Return False
            _scrollOffset = nextOffset
            _hoverRow = HitRow(ptPx)
            StartAvatarOverflowContentMotion(_hoverRow)
            RequestInvalidate()
            Return True
        End Function

        Public Function KeyDownFloat(ctx As MASThemeContext,
                                     keyCode As Keys) As Boolean Implements IMASFloatRoutedInputContent.KeyDownFloat
            Select Case keyCode
                Case Keys.Escape
                    Close(MASFloatCloseReason.EscapeKey)
                    Return True
                Case Keys.Down
                    MoveHover(1)
                    Return True
                Case Keys.Up
                    MoveHover(-1)
                    Return True
                Case Keys.Home
                    SetHoverRow(0)
                    Return True
                Case Keys.End
                    SetHoverRow(_items.Count - 1)
                    Return True
                Case Keys.Enter, Keys.Space
                    Dim row As Integer = If(_hoverRow >= 0, _hoverRow, 0)
                    If row >= 0 AndAlso row < _items.Count Then
                        InvokeItem(_items(row).SourceIndex)
                        Return True
                    End If
            End Select
            Return False
        End Function

        Public Function KeyUpFloat(ctx As MASThemeContext,
                                   keyCode As Keys) As Boolean Implements IMASFloatRoutedInputContent.KeyUpFloat
            Return False
        End Function

        Public Function TextInputFloat(ctx As MASThemeContext,
                                       text As String) As Boolean Implements IMASFloatRoutedInputContent.TextInputFloat
            Return False
        End Function

        Public Function Win32ImeMessageFloat(ctx As MASThemeContext,
                                             hwnd As IntPtr,
                                             message As Integer,
                                             wParam As IntPtr,
                                             lParam As IntPtr) As Boolean Implements IMASFloatRoutedInputContent.Win32ImeMessageFloat
            Return False
        End Function

        Private Function HitRow(ptPx As SKPoint) As Integer
            If Not _rowsAreaPx.Contains(ptPx.X, ptPx.Y) Then Return -1
            Dim rowHeight As Single = Math.Max(1.0F, AvatarTokens.OverflowPopupRowHeightDip * ResolveDpiFromBounds())
            Dim visibleRow As Integer = CInt(Math.Floor((ptPx.Y - _rowsAreaPx.Top) / rowHeight))
            Dim sourceRow As Integer = _scrollOffset + visibleRow
            If sourceRow < 0 OrElse sourceRow >= _items.Count Then Return -1
            Return sourceRow
        End Function

        Private Function ResolveDpiFromBounds() As Single
            Dim rows As Integer = MASAvatarOverflowPopoverPolicy.ResolveVisibleRows(_items.Count)
            Dim rowsDip As Single = Math.Max(1.0F, rows * AvatarTokens.OverflowPopupRowHeightDip)
            If _rowsAreaPx.Height <= 0.0F Then Return 1.0F
            Return PixelSnap.SafeDpi(_rowsAreaPx.Height / rowsDip)
        End Function

        Private Sub MoveHover(delta As Integer)
            If _items.Count <= 0 Then Return
            Dim current As Integer = If(_hoverRow < 0, If(delta >= 0, -1, _items.Count), _hoverRow)
            SetHoverRow(current + delta)
        End Sub

        Private Sub SetHoverRow(value As Integer)
            If _items.Count <= 0 Then Return
            Dim nextRow As Integer = Math.Max(0, Math.Min(value, _items.Count - 1))
            If nextRow = _hoverRow Then Return
            _hoverRow = nextRow
            EnsureHoverVisible()
            StartAvatarOverflowContentMotion(nextRow)
            RequestInvalidate()
        End Sub

        Private Sub EnsureHoverVisible()
            If _hoverRow < 0 Then Return
            Dim visibleRows As Integer = MASAvatarOverflowPopoverPolicy.ResolveVisibleRows(_items.Count)
            If _hoverRow < _scrollOffset Then
                _scrollOffset = MASAvatarOverflowPopoverPolicy.NormalizeScrollOffset(_hoverRow, _items.Count)
            ElseIf _hoverRow >= _scrollOffset + visibleRows Then
                _scrollOffset = MASAvatarOverflowPopoverPolicy.NormalizeScrollOffset(_hoverRow - visibleRows + 1, _items.Count)
            End If
        End Sub

        Private Sub InvokeItem(sourceIndex As Integer)
            Try
                If _onItemInvoked IsNot Nothing Then _onItemInvoked.Invoke(sourceIndex)
            Catch masCaughtException1 As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowInputBoundary(masCaughtException1, "MASAvatarOverflowFloatContent.ItemInvoked")
            End Try
            Close(MASFloatCloseReason.Accepted)
        End Sub

        Private Sub Close(reason As MASFloatCloseReason)
            If _session Is Nothing Then Return
            Try
                _session.Close(reason)
            Catch masCaughtException2 As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowInputBoundary(masCaughtException2, "MASAvatarOverflowFloatContent.Close")
            End Try
        End Sub

        Private Sub RequestInvalidate()
            If _session Is Nothing Then Return
            Try
                _session.RequestInvalidate()
            Catch masCaughtException3 As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowInputBoundary(masCaughtException3, "MASAvatarOverflowFloatContent.RequestInvalidate")
            End Try
        End Sub

        Private Shared Function ResolveDetailText(item As MASAvatarOverflowItem) As String
            If item IsNot Nothing AndAlso item.ShowPresence AndAlso Not String.IsNullOrWhiteSpace(item.PresenceText) Then
                Return item.PresenceText
            End If
            Return AvatarTokens.OverflowPopupDefaultDetail
        End Function

        Private Shared Function ResolveRightToLeft() As Boolean
            Return Nexamas.UI.Localization.MASLocalization.IsCurrentRightToLeft()
        End Function
    End Class

End Namespace
