Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports Nexamas.UI.TextInput
Imports Nexamas.UI.TextRendering
Imports SkiaSharp

Namespace Nexamas.UI.Quality

    ''' <summary>
    ''' Phase-6 proof for DPI-05 and DPI-06.
    ''' It verifies that paragraph measurement, wrap segmentation, render paragraph layout,
    ''' and ellipsis fitting are routed through the shaped measurement gateway.
    ''' </summary>
    Friend NotInheritable Class MASDpiTextMeasurementParityGate
        Friend Const WrapParityRecipeName As String = "DPI-05.ParagraphWrapRenderMeasurementParity"
        Friend Const EllipsisParityRecipeName As String = "DPI-06.ShapedEllipsisMeasurementParity"
        Friend Const GatewayRecipeName As String = "DPI-06.OfficialShapedMeasurementGateway"

        Private Const MaxWidthPx As Single = 148.0F
        Private Const TolerancePx As Single = 0.75F

        Private Sub New()
        End Sub

        Friend Shared Function Passes() As Boolean
            Return ProbeParagraphWrapRenderMeasurementParity() AndAlso
                   ProbeShapedEllipsisMeasurementParity() AndAlso
                   ProbeOfficialGatewayForRepeatedMeasurements()
        End Function

        Private Shared Function ProbeParagraphWrapRenderMeasurementParity() As Boolean
            Using paint As SKPaint = CreateProofPaint()
                Dim text As String = "Arabic مرحبا بالعالم English CJK 漢字かな emoji 😀🚀" & vbLf &
                                     "longword-supercalifragilistic-expialidocious"
                Dim document As MASTextMultilineDocument = MASTextMultilineDocument.FromText(text)
                Dim content As New SKRect(0.0F, 0.0F, MaxWidthPx, 240.0F)

                Dim layout As MASTextParagraphLayout =
                    MASTextParagraphLayout.Create(
                        document:=document,
                        contentR:=content,
                        paint:=paint,
                        verticalScrollOffsetPx:=0.0F,
                        wordWrap:=True,
                        horizontalScrollOffsetPx:=0.0F,
                        crispRendering:=False)

                Dim measured As MASTextParagraphMeasureResult =
                    MASTextLayoutMeasurementGateway.MeasureParagraph(
                        text:=text,
                        maxWidthPx:=MaxWidthPx,
                        paint:=paint,
                        allowWrap:=True,
                        normalizeLineEndings:=True)

                If layout Is Nothing OrElse measured Is Nothing Then Return False
                If layout.LineCount <> measured.LineCount Then Return False
                If Math.Abs(layout.TotalHeight - measured.Size.Height) > TolerancePx Then Return False

                For Each line As MASTextWrappedLine In layout.Lines
                    If line Is Nothing Then Continue For
                    Dim lineWidth As Single = MASTextLayoutMeasurementGateway.MeasureShapedWidth(line.Text, paint)
                    If lineWidth > MaxWidthPx + TolerancePx Then Return False
                Next

                Return True
            End Using
        End Function

        Private Shared Function ProbeShapedEllipsisMeasurementParity() As Boolean
            Using paint As SKPaint = CreateProofPaint()
                Dim samples As String() = {
                    "مرحبا بالعالم داخل واجهة عربية طويلة",
                    "CJK 漢字かなカナ very long label",
                    "emoji 😀🚀😃 mixed text sample",
                    "Latin office text with complex suffix"
                }

                For Each sample As String In samples
                    Dim fitted As String = Nexamas.UI.MASTextCore.FitEllipsis(sample, MaxWidthPx, paint)
                    If String.IsNullOrEmpty(fitted) Then Return False
                    If Not fitted.EndsWith("…", StringComparison.Ordinal) AndAlso
                       MASTextLayoutMeasurementGateway.MeasureShapedWidth(sample, paint) > MaxWidthPx + TolerancePx Then
                        Return False
                    End If

                    Dim fittedWidth As Single = MASTextLayoutMeasurementGateway.MeasureShapedWidth(fitted, paint)
                    Dim ellipsisWidth As Single = MASTextLayoutMeasurementGateway.MeasureShapedWidth("…", paint)
                    If fittedWidth > MaxWidthPx + TolerancePx AndAlso ellipsisWidth <= MaxWidthPx Then Return False
                Next

                Return True
            End Using
        End Function

        Private Shared Function ProbeOfficialGatewayForRepeatedMeasurements() As Boolean
            Using paint As SKPaint = CreateProofPaint()
                Dim session As MASTextWidthMeasureSession = MASTextWidthMeasureSession.ForPaint(paint)
                Dim sample As String = "مرحبا CJK 漢字 emoji 😀 repeated"

                Dim sessionWidth As Single = session.Measure(sample)
                Dim gatewayWidth As Single = MASTextLayoutMeasurementGateway.MeasureShapedWidth(sample, paint)

                If Math.Abs(sessionWidth - gatewayWidth) > TolerancePx Then Return False

                Dim segments As IReadOnlyList(Of MASTextWrapSegment) =
                    MASTextLayoutMeasurementGateway.BuildWrapSegments(sample, MaxWidthPx, paint, wordWrap:=True)

                If segments Is Nothing OrElse segments.Count = 0 Then Return False

                For Each segment As MASTextWrapSegment In segments
                    Dim part As String = MASTextLayoutMeasurementGateway.SafeSubstring(sample, segment.Start, segment.Length)
                    If MASTextLayoutMeasurementGateway.MeasureShapedWidth(part, paint) > MaxWidthPx + TolerancePx Then Return False
                Next

                Return True
            End Using
        End Function

        Private Shared Function CreateProofPaint() As SKPaint
            Return New SKPaint With {
                .IsAntialias = True,
                .SubpixelText = True,
                .Typeface = SKTypeface.Default,
                .TextSize = 16.0F,
                .Color = SKColors.Black
            }
        End Function
    End Class

End Namespace
