Option Strict On
Option Explicit On

Imports System
Imports System.Globalization
Imports Nexamas.UI.Motion

Namespace Nexamas.UI.Quality

    ''' <summary>
    ''' Runtime pressure proof that host-scoped Motion clocks advance only their own consumers
    ''' at 1k/10k scale and never create global per-paint pressure across hosts.
    ''' </summary>
    Friend NotInheritable Class MASMotionConsumerPressureGate

        Private Const SmallPressureConsumerCount As Integer = 1000
        Private Const LargePressureConsumerCount As Integer = 10000

        Private Sub New()
        End Sub

        Friend Shared Function Passes() As Boolean
            Dim previousMode As MASMotionReducedMotionMode = MASMotionSystem.ReducedMotionMode

            Try
                MASMotionSystem.ReducedMotionMode = MASMotionReducedMotionMode.FullMotion

                Return ProbeHostScopedPressure(SmallPressureConsumerCount) AndAlso
                       ProbeHostScopedPressure(LargePressureConsumerCount) AndAlso
                       ProbeAggregateCountUsesKnownHostClocksOnly()
            Catch ex As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDiagnosticOnly(ex, "MASMotionConsumerPressureGate")
                Return False
            Finally
                MASMotionSystem.ReducedMotionMode = previousMode
            End Try
        End Function

        Private Shared Function ProbeHostScopedPressure(consumerCount As Integer) As Boolean
            If consumerCount <= 0 Then Return False

            Using clockA As New MASMotionFrameClock("pressure-a-" & consumerCount.ToString(CultureInfo.InvariantCulture))
                Using clockB As New MASMotionFrameClock("pressure-b-" & consumerCount.ToString(CultureInfo.InvariantCulture))
                    Dim ownersA As Object() = CreateOwners(consumerCount)
                    Dim ownersB As Object() = CreateOwners(consumerCount)
                    Dim advancesA As Integer = 0
                    Dim advancesB As Integer = 0
                    Dim requestsA As Integer = 0
                    Dim requestsB As Integer = 0

                    For i As Integer = 0 To consumerCount - 1
                        Dim ownerA As Object = ownersA(i)
                        clockA.Register(
                            owner:=ownerA,
                            consumerName:="pressure-a",
                            requestFrame:=Sub()
                                              requestsA += 1
                                          End Sub,
                            advanceFrame:=Function(deltaMs As Integer)
                                              advancesA += 1
                                              Return True
                                          End Function)

                        Dim ownerB As Object = ownersB(i)
                        clockB.Register(
                            owner:=ownerB,
                            consumerName:="pressure-b",
                            requestFrame:=Sub()
                                              requestsB += 1
                                          End Sub,
                            advanceFrame:=Function(deltaMs As Integer)
                                              advancesB += 1
                                              Return True
                                          End Function)
                    Next

                    If clockA.ActiveConsumerCount() <> consumerCount Then Return False
                    If clockB.ActiveConsumerCount() <> consumerCount Then Return False
                    If requestsA <> consumerCount Then Return False
                    If requestsB <> consumerCount Then Return False

                    If Not clockA.AdvanceScheduledAnimations() Then Return False

                    If advancesA <> consumerCount Then Return False
                    If advancesB <> 0 Then Return False
                    If requestsA <> consumerCount * 2 Then Return False
                    If requestsB <> consumerCount Then Return False
                    If clockA.ActiveConsumerCount() <> consumerCount Then Return False
                    If clockB.ActiveConsumerCount() <> consumerCount Then Return False

                    Return True
                End Using
            End Using
        End Function

        Private Shared Function ProbeAggregateCountUsesKnownHostClocksOnly() As Boolean
            Dim before As Integer = MASMotionSystem.ActiveFrameConsumerCount()

            Using clock As New MASMotionFrameClock("pressure-aggregate")
                Dim owner As New Object()
                clock.Register(
                    owner:=owner,
                    consumerName:="pressure-aggregate",
                    requestFrame:=Sub()
                                  End Sub,
                    advanceFrame:=Function(deltaMs As Integer)
                                      Return True
                                  End Function)

                If MASMotionSystem.ActiveFrameConsumerCount() < before + 1 Then Return False
            End Using

            Return MASMotionSystem.ActiveFrameConsumerCount() <= before
        End Function

        Private Shared Function CreateOwners(count As Integer) As Object()
            Dim owners(count - 1) As Object
            For i As Integer = 0 To count - 1
                owners(i) = New Object()
            Next
            Return owners
        End Function

    End Class

End Namespace
