Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports Nexamas.UI.Components
Imports Nexamas.UI.Diagnostics
Imports Nexamas.UI.Virtualization
Imports SkiaSharp

Namespace Nexamas.UI.Quality

    ''' <summary>
    ''' Phase-15 residual proof for VIRT-R01..VIRT-R06. The probes target SDK-launch blockers in the shared virtualization
    ''' foundation: huge-offset precision, fractional-DPI invalidation, explicit large-summary pressure, fast-scroll plan pressure,
    ''' tile-grid fallback hit-test visibility, and off-window accessibility navigation over realized-only rendering.
    ''' </summary>
    Friend NotInheritable Class MASVirtualizationResidualReviewGate

        Private Const HugeItemCount As Integer = 1000000
        Private Const HugeEstimatedExtentPx As Single = 10000.25F
        Private Const RequiredSummaryRowCount As Integer = 100000
        Private Const FastScrollUpdates As Integer = 128
        Private Const FastScrollItemCount As Integer = 100000
        Private Const FastScrollExtentPx As Single = 36.0F
        Private Const FastScrollViewportExtentPx As Single = 360.0F

        Private Sub New()
        End Sub

        Friend Shared Function Passes() As Boolean
            Return RunProbe(AddressOf ProbeDoublePrecisionLargeExtents) AndAlso
                   RunProbe(AddressOf ProbeIncrementalMeasurementPrefixRebuild) AndAlso
                   RunProbe(AddressOf ProbeFractionalControlSizeRevision) AndAlso
                   RunProbe(AddressOf ProbeDataGridSummaryAlways100kPolicy) AndAlso
                   RunProbe(AddressOf ProbeFastScrollAllocationBudget) AndAlso
                   RunProbe(AddressOf ProbeTileGridHitTestFallbackDiagnostic) AndAlso
                   RunProbe(AddressOf ProbeOffscreenAccessibilityBridgeWithRealizedOnlyRendering)
        End Function

        Private Shared Function RunProbe(probe As Func(Of Boolean)) As Boolean
            Try
                Return probe.Invoke()
            Catch ex As Exception
                MASExceptionSilencer.SwallowDiagnosticOnly(ex, "MASVirtualizationResidualReviewGate")
                Return False
            End Try
        End Function

        Private Shared Function ProbeDoublePrecisionLargeExtents() As Boolean
            Dim controller As New MASVirtualizedItemsController(
                New MASVirtualizationOptions(
                    itemCount:=HugeItemCount,
                    estimatedItemExtentPx:=HugeEstimatedExtentPx,
                    overscanItemCount:=1,
                    axis:=MASVirtualizationAxis.Vertical,
                    extentStrategy:=MASVirtualizationExtentStrategy.EstimatedWithMeasuredOverrides))

            Dim expectedTotal As Double = CDbl(HugeItemCount) * CDbl(HugeEstimatedExtentPx)
            Dim totalDouble As Double = controller.TotalExtentPxDouble()
            Dim totalSingle As Single = controller.TotalExtentPx()
            If Math.Abs(totalDouble - expectedTotal) > 0.0001R Then Return False
            If Math.Abs(totalDouble - CDbl(totalSingle)) <= 0.0R Then Return False

            Dim targetIndex As Integer = HugeItemCount - 1
            Dim expectedOffset As Double = CDbl(targetIndex) * CDbl(HugeEstimatedExtentPx)
            Dim offsetDouble As Double = controller.ResolveOffsetForIndexDouble(targetIndex)
            If Math.Abs(offsetDouble - expectedOffset) > 0.0001R Then Return False

            Dim request As MASVirtualizationScrollRequest = controller.CreateScrollToIndexRequest(
                targetIndex,
                New MASVirtualizationViewport(0.0R, 800.0R),
                MASVirtualizationAlignment.Start)

            Return request IsNot Nothing AndAlso
                   Math.Abs(request.TargetOffsetPxDouble - CDbl(request.TargetOffsetPx)) > 0.0R AndAlso
                   request.TotalExtentPxDouble = totalDouble
        End Function

        Private Shared Function ProbeIncrementalMeasurementPrefixRebuild() As Boolean
            Dim cache As New MASVirtualizationMeasurementCache()
            Const measuredCount As Integer = 1000
            Const fallbackExtentPx As Single = 20.0F

            For index As Integer = 0 To measuredCount - 1
                cache.SetMeasuredExtent(index, fallbackExtentPx + CSng(index Mod 5))
            Next

            Dim initialTotal As Double = cache.ResolveTotalExtentDouble(measuredCount, fallbackExtentPx)
            If initialTotal <= 0.0R Then Return False
            If cache.LastPrefixRebuildStartIndexForTests <> 0 Then Return False
            If cache.LastPrefixRebuildCountForTests <> measuredCount Then Return False

            cache.SetMeasuredExtent(900, fallbackExtentPx + 42.0F)
            Dim updatedTotal As Double = cache.ResolveTotalExtentDouble(measuredCount, fallbackExtentPx)
            If updatedTotal <= initialTotal Then Return False
            If cache.LastPrefixRebuildStartIndexForTests < 900 Then Return False
            If cache.LastPrefixRebuildCountForTests > 100 Then Return False

            cache.SetMeasuredExtent(measuredCount, fallbackExtentPx + 64.0F)
            Dim appendedTotal As Double = cache.ResolveTotalExtentDouble(measuredCount + 1, fallbackExtentPx)

            Return appendedTotal > updatedTotal AndAlso
                   cache.LastPrefixRebuildStartIndexForTests >= measuredCount AndAlso
                   cache.LastPrefixRebuildCountForTests <= 1
        End Function

        Private Shared Function ProbeFractionalControlSizeRevision() As Boolean
            Dim first As Integer = MASLinearVirtualizationConsumerCoordinator.ResolveControlSizeRevision(320.125F, 480.0F)
            Dim second As Integer = MASLinearVirtualizationConsumerCoordinator.ResolveControlSizeRevision(320.375F, 480.0F)
            Dim repeated As Integer = MASLinearVirtualizationConsumerCoordinator.ResolveControlSizeRevision(320.125F, 480.0F)

            Return MASVirtualizationSizeRevision.FractionalPixelQuantum < 1.0R AndAlso
                   first <> second AndAlso
                   first = repeated
        End Function

        Private Shared Function ProbeDataGridSummaryAlways100kPolicy() As Boolean
            Dim view As New MASDataView()
            view.AddColumn("Id", "Id").ValueTypeCode = TypeCode.Int32
            view.AddColumn("Amount", "Amount").ValueTypeCode = TypeCode.Decimal
            view.ReplaceRows(CreateSummaryRows())

            Dim decision As MASDataGridSummaryPreparationDecision =
                MASDataGridSummaryPreparationPolicy.Evaluate(view, MASDataGridSummaryFooterMode.Always, automaticSourceRowLimit:=0)
            If decision Is Nothing OrElse Not decision.ShouldPrepare Then Return False
            If Not String.Equals(decision.ReasonCode, MASDataGridSummaryPreparationPolicy.ExplicitAlwaysReasonCode, StringComparison.Ordinal) Then Return False

            Dim message As String = MASDataGridSummaryPreparationPolicy.CreateExplicitAlwaysLargeDataPerformanceMessage(view)
            If String.IsNullOrWhiteSpace(message) Then Return False
            If Not message.Contains(MASDataGridSummaryPreparationPolicy.ExplicitAlwaysLargeDataPressureReasonCode) Then Return False
            If Not message.Contains(RequiredSummaryRowCount.ToString(Global.System.Globalization.CultureInfo.InvariantCulture)) Then Return False

            Dim snapshot As MASDataGridSummarySnapshot = view.PrepareVisibleSummarySnapshot()
            Return snapshot IsNot Nothing AndAlso
                   snapshot.IsReady AndAlso
                   snapshot.Row IsNot Nothing AndAlso
                   snapshot.Row.VisibleRowCount = RequiredSummaryRowCount AndAlso
                   snapshot.Row.HasContent
        End Function

        Private Shared Function ProbeFastScrollAllocationBudget() As Boolean
            Dim controller As New MASVirtualizedItemsController(
                New MASVirtualizationOptions(
                    itemCount:=FastScrollItemCount,
                    estimatedItemExtentPx:=FastScrollExtentPx,
                    overscanItemCount:=2,
                    axis:=MASVirtualizationAxis.Vertical,
                    extentStrategy:=MASVirtualizationExtentStrategy.EstimatedWithMeasuredOverrides))

            For stepIndex As Integer = 0 To FastScrollUpdates - 1
                Dim offsetPx As Double = CDbl(stepIndex * 7) * CDbl(FastScrollExtentPx)
                controller.Update(New MASVirtualizationViewport(offsetPx, CDbl(FastScrollViewportExtentPx)))
            Next

            Dim snapshot As MASVirtualizationPlanAllocationBudgetSnapshot = controller.CreatePlanAllocationBudgetSnapshot()
            Return snapshot IsNot Nothing AndAlso
                   snapshot.IsWithinBudget(FastScrollUpdates, maxLeaseBudget:=64, maxScratchCapacity:=128)
        End Function

        Private Shared Function ProbeTileGridHitTestFallbackDiagnostic() As Boolean
            Dim coordinator As New MASTileGridVirtualizationConsumerCoordinator()
            Dim itemIndex As Integer = coordinator.ResolveGridHitIndex(
                New SKPoint(24.0F, 24.0F),
                New SKRect(0.0F, 0.0F, 320.0F, 240.0F),
                gridLeftPx:=0.0F,
                gridTopPx:=0.0F,
                columnStepPx:=80.0F,
                rowExtentPx:=47.5F,
                viewportOffsetPx:=15.25F,
                columnCount:=4,
                itemCount:=1000)

            Dim diagnostic As MASVirtualizationHitTestFallbackDiagnostic = coordinator.LastHitTestFallbackDiagnostic
            Return itemIndex >= 0 AndAlso
                   diagnostic IsNot Nothing AndAlso
                   diagnostic.FallbackUsed AndAlso
                   diagnostic.IsVisibleDiagnostic AndAlso
                   diagnostic.HasVariableExtentMismatchRisk AndAlso
                   String.Equals(diagnostic.DiagnosticCode, MASVirtualizationHitTestFallbackDiagnostic.VariableExtentMismatchRiskCode, StringComparison.Ordinal)
        End Function

        Private Shared Function ProbeOffscreenAccessibilityBridgeWithRealizedOnlyRendering() As Boolean
            Dim report As MASVirtualizationAccessibleRangeReport = MASVirtualizationAccessibleRangeGate.EvaluateCurrentConsumers()
            If report Is Nothing OrElse Not report.IsReady Then Return False

            Dim coordinator As New MASLinearVirtualizationConsumerCoordinator()
            coordinator.Configure(
                itemCount:=FastScrollItemCount,
                estimatedItemExtentPx:=FastScrollExtentPx,
                overscanItemCount:=2,
                axis:=MASVirtualizationAxis.Vertical,
                extentStrategy:=MASVirtualizationExtentStrategy.EstimatedWithMeasuredOverrides)

            Dim initialPlan As MASVirtualizationRealizationPlan = coordinator.UpdateViewport(0.0F, FastScrollViewportExtentPx)
            Dim targetIndex As Integer = FastScrollItemCount - 1
            If initialPlan Is Nothing OrElse initialPlan.Range Is Nothing OrElse initialPlan.Range.Contains(targetIndex) Then Return False

            Dim request As MASVirtualizationScrollRequest = coordinator.CreateScrollToIndexRequest(targetIndex, 0.0F, FastScrollViewportExtentPx, MASVirtualizationAlignment.Start)
            If request Is Nothing OrElse request.Index <> targetIndex Then Return False

            Dim targetPlan As MASVirtualizationRealizationPlan = coordinator.UpdateViewport(request.TargetOffsetPx, FastScrollViewportExtentPx)
            Return targetPlan IsNot Nothing AndAlso
                   targetPlan.Range IsNot Nothing AndAlso
                   targetPlan.Range.Contains(targetIndex) AndAlso
                   targetPlan.RealizedCount < FastScrollItemCount
        End Function

        Private Shared Iterator Function CreateSummaryRows() As IEnumerable(Of Object())
            For index As Integer = 0 To RequiredSummaryRowCount - 1
                Yield New Object() {
                    index,
                    CDec(index Mod 1000)
                }
            Next
        End Function

    End Class

End Namespace
