Option Strict On
Option Explicit On

Imports System.Collections.Generic
Imports System.Collections.ObjectModel

Namespace Nexamas.UI.Virtualization

    ''' <summary>
    ''' Internal accessibility contract for a virtualized consumer range. The binding proves that accessibility/navigation
    ''' semantics keep logical item identity and total logical count even when the rendered plan is bounded to the realized window.
    ''' It does not create UI Automation providers and does not expose virtualization as public API.
    ''' </summary>
    Friend NotInheritable Class MASVirtualizationAccessibleRangeBinding
        Private ReadOnly _composedThroughConsumerIds As IReadOnlyList(Of String)

        Friend Sub New(consumerId As String,
                       displayName As String,
                       logicalItemCount As Integer,
                       offscreenTargetIndex As Integer,
                       viewportExtentPx As Single,
                       maxRealizedRequestCount As Integer,
                       usesScrollToIndexBridge As Boolean,
                       exposesLogicalPositionMetadata As Boolean,
                       keepsSnapshotBoundedToRealizedRange As Boolean,
                       Optional isTileGrid As Boolean = False,
                       Optional columnCount As Integer = 1,
                       Optional isComposed As Boolean = False,
                       Optional composedThroughConsumerIds As IEnumerable(Of String) = Nothing)
            Me.ConsumerId = If(consumerId, String.Empty).Trim()
            Me.DisplayName = If(displayName, String.Empty).Trim()
            Me.LogicalItemCount = System.Math.Max(0, logicalItemCount)
            Me.OffscreenTargetIndex = System.Math.Max(0, offscreenTargetIndex)
            Me.ViewportExtentPx = System.Math.Max(0.0F, MASVirtualizationNumericGuard.NormalizeNonNegative(viewportExtentPx))
            Me.MaxRealizedRequestCount = System.Math.Max(0, maxRealizedRequestCount)
            Me.UsesScrollToIndexBridge = usesScrollToIndexBridge
            Me.ExposesLogicalPositionMetadata = exposesLogicalPositionMetadata
            Me.KeepsSnapshotBoundedToRealizedRange = keepsSnapshotBoundedToRealizedRange
            Me.IsTileGrid = isTileGrid
            Me.ColumnCount = System.Math.Max(1, columnCount)
            Me.IsComposed = isComposed
            _composedThroughConsumerIds = NormalizeComposedThroughConsumerIds(composedThroughConsumerIds)
        End Sub

        Friend ReadOnly Property ConsumerId As String
        Friend ReadOnly Property DisplayName As String
        Friend ReadOnly Property LogicalItemCount As Integer
        Friend ReadOnly Property OffscreenTargetIndex As Integer
        Friend ReadOnly Property ViewportExtentPx As Single
        Friend ReadOnly Property MaxRealizedRequestCount As Integer
        Friend ReadOnly Property UsesScrollToIndexBridge As Boolean
        Friend ReadOnly Property ExposesLogicalPositionMetadata As Boolean
        Friend ReadOnly Property KeepsSnapshotBoundedToRealizedRange As Boolean
        Friend ReadOnly Property IsTileGrid As Boolean
        Friend ReadOnly Property ColumnCount As Integer
        Friend ReadOnly Property IsComposed As Boolean

        Friend ReadOnly Property ComposedThroughConsumerIds As IReadOnlyList(Of String)
            Get
                Return _composedThroughConsumerIds
            End Get
        End Property

        Friend ReadOnly Property IsStructurallyValid As Boolean
            Get
                Return ConsumerId.Length > 0 AndAlso
                       DisplayName.Length > 0 AndAlso
                       LogicalItemCount > 0 AndAlso
                       OffscreenTargetIndex >= 0 AndAlso
                       OffscreenTargetIndex < LogicalItemCount AndAlso
                       ViewportExtentPx > 0.0F AndAlso
                       MaxRealizedRequestCount > 0 AndAlso
                       UsesScrollToIndexBridge AndAlso
                       ExposesLogicalPositionMetadata AndAlso
                       KeepsSnapshotBoundedToRealizedRange AndAlso
                       (Not IsComposed OrElse _composedThroughConsumerIds.Count > 0)
            End Get
        End Property

        Private Shared Function NormalizeComposedThroughConsumerIds(ids As IEnumerable(Of String)) As IReadOnlyList(Of String)
            Dim result As New List(Of String)()

            If ids IsNot Nothing Then
                For Each rawId As String In ids
                    Dim id As String = If(rawId, String.Empty).Trim()
                    If id.Length = 0 Then Continue For
                    If result.Contains(id) Then Continue For
                    result.Add(id)
                Next
            End If

            Return New ReadOnlyCollection(Of String)(result.ToArray())
        End Function
    End Class

End Namespace
