Option Strict On
Option Explicit On

Imports System.Collections.Generic
Imports System.Linq

Namespace Nexamas.UI.Virtualization

    ''' <summary>
    ''' Commercial-scope gate for P1-2: render/window virtualization must not be presented as data/projection virtualization.
    ''' This gate does not introduce a new projection engine. It records and enforces the current ownership truth: DataView
    ''' and TreeView projection are surface-owned, explicit full-projection passes, separate from bounded render realization.
    ''' </summary>
    Friend NotInheritable Class MASVirtualizationProjectionScopeGate
        Friend Const RequiredProjectionScopeSurfaceCount As Integer = 2

        Friend Const EmptyCatalogCode As String = "MASVirtualizationProjectionScope.EmptyCatalog"
        Friend Const DuplicateSurfaceCode As String = "MASVirtualizationProjectionScope.DuplicateSurface"
        Friend Const MissingRequiredSurfaceCode As String = "MASVirtualizationProjectionScope.MissingRequiredSurface"
        Friend Const InvalidBindingCode As String = "MASVirtualizationProjectionScope.InvalidBinding"
        Friend Const HiddenCoreProjectionClaimCode As String = "MASVirtualizationProjectionScope.HiddenCoreProjectionClaim"

        Private Shared ReadOnly RequiredSurfaceIds As IReadOnlyList(Of String) =
            New String() {
                "MASDataView",
                "MASTreeView"
            }

        Private Sub New()
        End Sub

        Friend Shared Function EvaluateCurrentScopes() As MASVirtualizationProjectionScopeReport
            Return Evaluate(MASVirtualizationProjectionScopeCatalog.GetCurrentProjectionScopes())
        End Function

        Friend Shared Function Evaluate(bindings As IEnumerable(Of MASVirtualizationProjectionScopeBinding)) As MASVirtualizationProjectionScopeReport
            Dim safeBindings = If(bindings, Enumerable.Empty(Of MASVirtualizationProjectionScopeBinding)()).Where(Function(binding) binding IsNot Nothing).ToArray()
            Dim findings As New List(Of MASVirtualizationReadinessFinding)()
            Dim surfaceOwnedProjectionIds As New List(Of String)()

            If safeBindings.Length = 0 Then
                findings.Add(New MASVirtualizationReadinessFinding(EmptyCatalogCode, "Projection-scope catalog must not be empty.", MASVirtualizationFindingSeverity.Error))
                Return New MASVirtualizationProjectionScopeReport(safeBindings, findings, surfaceOwnedProjectionIds)
            End If

            Dim ids As New HashSet(Of String)(StringComparer.Ordinal)
            For Each binding As MASVirtualizationProjectionScopeBinding In safeBindings
                If Not binding.IsStructurallyValid Then
                    findings.Add(New MASVirtualizationReadinessFinding(InvalidBindingCode, "Projection-scope binding is missing identity, source owner, operation, explicit full-projection admission, or separate projection contract: " & binding.Id, MASVirtualizationFindingSeverity.Error))
                End If

                If Not ids.Add(binding.Id) Then
                    findings.Add(New MASVirtualizationReadinessFinding(DuplicateSurfaceCode, "Duplicate projection-scope surface id: " & binding.Id, MASVirtualizationFindingSeverity.Error))
                End If

                If binding.VirtualizationCoreOwnsProjection Then
                    findings.Add(New MASVirtualizationReadinessFinding(HiddenCoreProjectionClaimCode, "Virtualization core must not claim ownership of source projection: " & binding.Id, MASVirtualizationFindingSeverity.Error))
                End If

                If binding.IsSurfaceOwnedProjection Then AddSurfaceOwned(surfaceOwnedProjectionIds, binding.Id)
            Next

            For Each requiredId As String In RequiredSurfaceIds
                If Not ids.Contains(requiredId) Then
                    findings.Add(New MASVirtualizationReadinessFinding(MissingRequiredSurfaceCode, "Missing projection-scope binding for current surface: " & requiredId, MASVirtualizationFindingSeverity.Error))
                End If
            Next

            Return New MASVirtualizationProjectionScopeReport(safeBindings, findings, surfaceOwnedProjectionIds)
        End Function

        Private Shared Sub AddSurfaceOwned(surfaceOwnedProjectionIds As List(Of String), id As String)
            Dim normalized As String = If(id, String.Empty).Trim()
            If normalized.Length = 0 Then Return
            If Not surfaceOwnedProjectionIds.Contains(normalized) Then surfaceOwnedProjectionIds.Add(normalized)
        End Sub

    End Class

End Namespace
