Option Strict On
Option Explicit On

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

Namespace Nexamas.UI.Virtualization

    ''' <summary>
    ''' Report proving that source/data projection is not hidden inside the render virtualization commercial claim.
    ''' </summary>
    Friend NotInheritable Class MASVirtualizationProjectionScopeReport
        Private ReadOnly _bindings As IReadOnlyList(Of MASVirtualizationProjectionScopeBinding)
        Private ReadOnly _findings As IReadOnlyList(Of MASVirtualizationReadinessFinding)
        Private ReadOnly _surfaceOwnedProjectionIds As IReadOnlyList(Of String)

        Friend Sub New(bindings As IEnumerable(Of MASVirtualizationProjectionScopeBinding),
                       findings As IEnumerable(Of MASVirtualizationReadinessFinding),
                       surfaceOwnedProjectionIds As IEnumerable(Of String))
            _bindings = New ReadOnlyCollection(Of MASVirtualizationProjectionScopeBinding)(If(bindings, Enumerable.Empty(Of MASVirtualizationProjectionScopeBinding)()).Where(Function(binding) binding IsNot Nothing).ToArray())
            _findings = New ReadOnlyCollection(Of MASVirtualizationReadinessFinding)(If(findings, Enumerable.Empty(Of MASVirtualizationReadinessFinding)()).Where(Function(finding) finding IsNot Nothing).ToArray())
            _surfaceOwnedProjectionIds = New ReadOnlyCollection(Of String)(NormalizeIds(surfaceOwnedProjectionIds))
        End Sub

        Friend ReadOnly Property Bindings As IReadOnlyList(Of MASVirtualizationProjectionScopeBinding)
            Get
                Return _bindings
            End Get
        End Property

        Friend ReadOnly Property Findings As IReadOnlyList(Of MASVirtualizationReadinessFinding)
            Get
                Return _findings
            End Get
        End Property

        Friend ReadOnly Property SurfaceOwnedProjectionIds As IReadOnlyList(Of String)
            Get
                Return _surfaceOwnedProjectionIds
            End Get
        End Property

        Friend ReadOnly Property ProjectionScopeSurfaceCount As Integer
            Get
                Return _bindings.Count
            End Get
        End Property

        Friend ReadOnly Property SurfaceOwnedProjectionCount As Integer
            Get
                Return _surfaceOwnedProjectionIds.Count
            End Get
        End Property

        Friend ReadOnly Property NoVirtualizationCoreProjectionOwnership As Boolean
            Get
                Return _bindings.Count > 0 AndAlso _bindings.All(Function(binding) Not binding.VirtualizationCoreOwnsProjection)
            End Get
        End Property

        Friend ReadOnly Property AllProjectionScaleRequiresSeparateGate As Boolean
            Get
                Return _bindings.Count > 0 AndAlso _bindings.All(Function(binding) binding.ProjectionScaleRequiresSeparateGate)
            End Get
        End Property

        Friend ReadOnly Property AllFullProjectionPassesAreExplicit As Boolean
            Get
                Return _bindings.Count > 0 AndAlso _bindings.All(Function(binding) binding.AdmitsFullProjectionPass)
            End Get
        End Property

        Friend ReadOnly Property IsReady As Boolean
            Get
                Return _bindings.Count > 0 AndAlso
                       _surfaceOwnedProjectionIds.Count = _bindings.Count AndAlso
                       NoVirtualizationCoreProjectionOwnership AndAlso
                       AllProjectionScaleRequiresSeparateGate AndAlso
                       AllFullProjectionPassesAreExplicit AndAlso
                       Not _findings.Any(Function(finding) finding.Severity = MASVirtualizationFindingSeverity.Error)
            End Get
        End Property

        Private Shared Function NormalizeIds(ids As IEnumerable(Of String)) As String()
            Dim result As New List(Of String)()
            If ids Is Nothing Then Return result.ToArray()

            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

            Return result.ToArray()
        End Function

    End Class

End Namespace
