Option Strict On
Option Explicit On

Imports System
Imports Nexamas.UI.TextInput
Imports Nexamas.UI.Values
Imports SkiaSharp

Namespace Nexamas.UI.Quality

    ''' <summary>
    ''' Phase-5 DPI/TextInput paint lifecycle proof.
    ''' </summary>
    ''' <remarks>
    ''' DPI-01: text-input render/hit-test/caret paths use a control-owned paint cache
    ''' instead of leaking a new SKPaint clone per call.
    ''' DPI-02: public MASTypography.GetPaint returns a caller-owned clone while the
    ''' internal shared paint remains Friend-only and isolated from mutation/disposal.
    ''' </remarks>
    Friend NotInheritable Class MASDpiTextInputPaintLifecycleGate

        Friend Const RenderHitTestPaintLoopCount As Integer = 10000
        Friend Const PublicPaintIsolationRecipeName As String = "DPI-02.PublicTypographyPaintCloneIsolation"
        Friend Const TextInputPaintLifecycleRecipeName As String = "DPI-01.TextInputOwnedPaintLifecycle"

        Private Sub New()
        End Sub

        Friend Shared Function Passes() As Boolean
            Return ProbePublicTypographyPaintIsolation() AndAlso
                   ProbeTextInputOwnedPaintLifecycle()
        End Function

        Private Shared Function ProbePublicTypographyPaintIsolation() As Boolean
            Using typography As New MASTypography(1.0F)
                Dim sharedBefore As SKPaint = typography.GetSharedPaint(MASTypography.MASTextStyle.FieldText, SKColors.Black)
                If sharedBefore Is Nothing Then Return False

                Dim sharedTextSize As Single = sharedBefore.TextSize
                Dim sharedColor As SKColor = sharedBefore.Color

                Dim publicPaint As SKPaint = typography.GetPaint(MASTypography.MASTextStyle.FieldText, SKColors.Black)
                If publicPaint Is Nothing Then Return False
                If Object.ReferenceEquals(publicPaint, sharedBefore) Then Return False

                publicPaint.TextSize = 777.0F
                publicPaint.Color = SKColors.Magenta
                publicPaint.Dispose()

                Dim sharedAfter As SKPaint = typography.GetSharedPaint(MASTypography.MASTextStyle.FieldText, SKColors.Black)
                If Not Object.ReferenceEquals(sharedBefore, sharedAfter) Then Return False
                If Math.Abs(sharedAfter.TextSize - sharedTextSize) > 0.01F Then Return False
                If CUInt(sharedAfter.Color) <> CUInt(sharedColor) Then Return False

                Using secondPublicPaint As SKPaint = typography.GetPaint(MASTypography.MASTextStyle.FieldText, SKColors.Black)
                    If secondPublicPaint Is Nothing Then Return False
                    If Object.ReferenceEquals(secondPublicPaint, sharedAfter) Then Return False
                    If Math.Abs(secondPublicPaint.TextSize - sharedTextSize) > 0.01F Then Return False
                    If CUInt(secondPublicPaint.Color) <> CUInt(sharedColor) Then Return False
                End Using
            End Using

            Return True
        End Function

        Private Shared Function ProbeTextInputOwnedPaintLifecycle() As Boolean
            Using typography As New MASTypography(1.0F)
                Using cache As New MASTextInputOwnedPaintCache()
                    Dim firstOwnedPaint As SKPaint = Nothing
                    Dim firstSignature As String = String.Empty

                    For i As Integer = 0 To RenderHitTestPaintLoopCount - 1
                        Using candidate As SKPaint = typography.CreatePaint(MASTypography.MASTextStyle.FieldText, SKColors.Black)
                            If candidate Is Nothing Then Return False

                            Dim owned As SKPaint = cache.AdoptOrReuse(candidate)
                            If owned Is Nothing Then Return False
                            If cache.ActivePaintCountForProof <> 1 Then Return False

                            If i = 0 Then
                                firstOwnedPaint = owned
                                firstSignature = cache.SignatureForProof
                            Else
                                If Not Object.ReferenceEquals(firstOwnedPaint, owned) Then Return False
                                If Not String.Equals(firstSignature, cache.SignatureForProof, StringComparison.Ordinal) Then Return False
                            End If
                        End Using
                    Next

                    Using differentCandidate As SKPaint = typography.CreatePaint(MASTypography.MASTextStyle.FieldText, SKColors.Blue)
                        Dim replacement As SKPaint = cache.AdoptOrReuse(differentCandidate)
                        If replacement Is Nothing Then Return False
                        If Object.ReferenceEquals(firstOwnedPaint, replacement) Then Return False
                        If cache.ActivePaintCountForProof <> 1 Then Return False
                    End Using

                    cache.Dispose()
                    If cache.ActivePaintCountForProof <> 0 Then Return False
                End Using
            End Using

            Return True
        End Function

    End Class

End Namespace
