Option Strict On
Option Explicit On

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

Namespace Nexamas.UI.Virtualization

    ''' <summary>
    ''' Commercial-scale governance gate for large-data/windowing surfaces. This gate does not make
    ''' domain-specific controls consume the shared virtualization controller. Instead, it requires every
    ''' large surface to be cataloged and either covered by the shared-controller behavior proof or by an
    ''' official bounded-window proof owned by that surface.
    ''' </summary>
    Friend NotInheritable Class MASLargeDataWindowingGate
        Friend Const RequiredSharedControllerSurfaceCount As Integer = 7
        Friend Const RequiredDomainSpecificWindowingSurfaceCount As Integer = 5

        Friend Const EmptyCatalogCode As String = "MASLargeDataWindowing.EmptyCatalog"
        Friend Const DuplicateSurfaceCode As String = "MASLargeDataWindowing.DuplicateSurface"
        Friend Const MissingRequiredSurfaceCode As String = "MASLargeDataWindowing.MissingRequiredSurface"
        Friend Const InvalidBindingCode As String = "MASLargeDataWindowing.InvalidBinding"
        Friend Const ProofFailedCode As String = "MASLargeDataWindowing.ProofFailed"

        Private Shared ReadOnly RequiredSurfaceIds As IReadOnlyList(Of String) =
            New String() {
                "MASListBox",
                "MASListView",
                "MASDataGrid",
                "MASTreeView",
                "MASTileBox",
                "MASDropDownListFloatContent",
                "MASFileExplorerView",
                "MASTreeGrid",
                "MASPivotTable",
                "MASKanbanBoard",
                "MASAgendaView",
                "MASDashboardGrid"
            }

        Private Sub New()
        End Sub

        Friend Shared Function EvaluateCurrentSurfaces(consumerBehaviorReport As MASVirtualizationConsumerBehaviorReport) As MASLargeDataWindowingReport
            Return Evaluate(MASLargeDataWindowingCatalog.GetCurrentWindowedSurfaces(), consumerBehaviorReport)
        End Function

        Friend Shared Function Evaluate(bindings As IEnumerable(Of MASLargeDataWindowingBinding),
                                        consumerBehaviorReport As MASVirtualizationConsumerBehaviorReport) As MASLargeDataWindowingReport
            Dim safeBindings = If(bindings, Enumerable.Empty(Of MASLargeDataWindowingBinding)()).Where(Function(binding) binding IsNot Nothing).ToArray()
            Dim findings As New List(Of MASVirtualizationReadinessFinding)()
            Dim provedSurfaceIds As New List(Of String)()

            If safeBindings.Length = 0 Then
                findings.Add(New MASVirtualizationReadinessFinding(EmptyCatalogCode, "Large-data/windowing catalog must not be empty.", MASVirtualizationFindingSeverity.Error))
                Return New MASLargeDataWindowingReport(safeBindings, findings, provedSurfaceIds)
            End If

            Dim ids As New HashSet(Of String)(StringComparer.Ordinal)
            For Each binding As MASLargeDataWindowingBinding In safeBindings
                If Not binding.IsStructurallyValid Then
                    findings.Add(New MASVirtualizationReadinessFinding(InvalidBindingCode, "Large-data/windowing binding is missing identity, type, ownership facts, or proof route: " & binding.Id, MASVirtualizationFindingSeverity.Error))
                End If

                If binding.SurfaceType IsNot Nothing AndAlso Not binding.SurfaceType.IsClass Then
                    findings.Add(New MASVirtualizationReadinessFinding(InvalidBindingCode, "Large-data/windowing binding must reference a class type: " & binding.Id, MASVirtualizationFindingSeverity.Error))
                End If

                If Not binding.SourceProjectionRemainsSurfaceOwned OrElse Not binding.LayoutRemainsSurfaceOwned OrElse Not binding.InputRemainsSurfaceOwned Then
                    findings.Add(New MASVirtualizationReadinessFinding(InvalidBindingCode, "Large-data/windowing binding leaks source projection, layout, or input ownership out of the surface: " & binding.Id, MASVirtualizationFindingSeverity.Error))
                End If

                If Not ids.Add(binding.Id) Then
                    findings.Add(New MASVirtualizationReadinessFinding(DuplicateSurfaceCode, "Duplicate large-data/windowing surface id: " & binding.Id, MASVirtualizationFindingSeverity.Error))
                End If
            Next

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

            Dim behaviorProvedIds As IReadOnlyList(Of String) = Array.Empty(Of String)()
            If consumerBehaviorReport IsNot Nothing AndAlso consumerBehaviorReport.ProvedConsumerIds IsNot Nothing Then
                behaviorProvedIds = consumerBehaviorReport.ProvedConsumerIds
            End If

            For Each binding As MASLargeDataWindowingBinding In safeBindings
                If binding.IsSharedControllerSurface Then
                    If consumerBehaviorReport IsNot Nothing AndAlso consumerBehaviorReport.IsReady AndAlso Global.System.Linq.Enumerable.Contains(behaviorProvedIds, binding.Id) Then
                        AddProved(provedSurfaceIds, binding.Id)
                    Else
                        findings.Add(New MASVirtualizationReadinessFinding(ProofFailedCode, "Shared-controller large-data surface is not covered by consumer behavior proof: " & binding.Id, MASVirtualizationFindingSeverity.Error))
                    End If
                    Continue For
                End If

                If binding.IsDomainSpecificWindowingSurface Then
                    Dim passed As Boolean = False
                    Try
                        passed = binding.ExecuteProof()
                    Catch ex As Exception
                        Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDiagnosticOnly(ex, "MASLargeDataWindowingGate." & binding.Id)
                        findings.Add(New MASVirtualizationReadinessFinding(ProofFailedCode, "Domain-specific windowing proof threw for " & binding.Id & ": " & ex.GetType().Name, MASVirtualizationFindingSeverity.Error))
                    End Try

                    If passed Then
                        AddProved(provedSurfaceIds, binding.Id)
                    Else
                        findings.Add(New MASVirtualizationReadinessFinding(ProofFailedCode, "Domain-specific windowing proof failed for " & binding.Id & " via " & binding.ProofName & ".", MASVirtualizationFindingSeverity.Error))
                    End If
                    Continue For
                End If

                findings.Add(New MASVirtualizationReadinessFinding(InvalidBindingCode, "Large-data/windowing binding is neither shared-controller nor domain-specific: " & binding.Id, MASVirtualizationFindingSeverity.Error))
            Next

            Return New MASLargeDataWindowingReport(safeBindings, findings, provedSurfaceIds)
        End Function

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

    End Class

End Namespace
