Option Strict On
Option Explicit On

Imports System
Imports Nexamas.UI.Controls
Imports SkiaSharp

Namespace Nexamas.UI.Components

    ''' <summary>
    ''' Friend-only helper for product-control hosted-content placement. It uses the
    ''' official MASControlBase child registration/layout placement path and avoids
    ''' any native panel, Showcase workaround, router, or wrapper ownership.
    ''' </summary>
    Friend NotInheritable Class MASHostedContentContractPolicy

        Private Sub New()
        End Sub

        Friend Shared Function NormalizeSlotKey(value As String,
                                                fallback As String) As String
            Dim text As String = If(value, String.Empty).Trim()
            If text.Length = 0 Then text = If(fallback, String.Empty).Trim()
            If text.Length = 0 Then Return String.Empty
            text = text.Replace(" "c, "-"c)
            If text.Length > 96 Then text = text.Substring(0, 96)
            Return text
        End Function

        Friend Shared Function CreateSnapshot(ownerComponentId As String,
                                             slotKey As String,
                                             slotKind As MASHostedContentSlotKind,
                                             child As MASControlBase,
                                             isVisible As Boolean,
                                             boundsLogical As SKRect,
                                             clipBoundsLogical As System.Nullable(Of SKRect),
                                             lifecycleGeneration As Integer) As MASHostedContentSlotSnapshot
            Dim childType As String = String.Empty
            Dim childName As String = String.Empty
            Dim hosted As Boolean = child IsNot Nothing AndAlso Not child.IsDisposedInternal
            If hosted Then
                childType = child.GetType().Name
                childName = If(child.Name, String.Empty)
            End If

            Dim hasPlacement As Boolean = hosted AndAlso IsUsableBounds(boundsLogical)
            Return New MASHostedContentSlotSnapshot(ownerComponentId,
                                                    slotKey,
                                                    slotKind,
                                                    childType,
                                                    childName,
                                                    hosted,
                                                    hosted AndAlso isVisible,
                                                    hasPlacement,
                                                    boundsLogical,
                                                    clipBoundsLogical,
                                                    lifecycleGeneration)
        End Function

        Friend Shared Sub PlaceChild(child As MASControlBase,
                                     boundsPx As SKRect,
                                     dpi As Single,
                                     Optional clipPx As System.Nullable(Of SKRect) = Nothing)
            If child Is Nothing OrElse child.IsDisposedInternal Then Return
            If dpi <= 0.01F OrElse Single.IsNaN(dpi) OrElse Single.IsInfinity(dpi) Then dpi = 1.0F
            If Not IsUsableBounds(boundsPx) Then
                child.Visible = False
                Return
            End If

            Dim boundsLogical As SKRect = ToLogicalRect(boundsPx, dpi)
            Dim clipLogical As System.Nullable(Of SKRect) = Nothing
            If clipPx.HasValue AndAlso IsUsableBounds(clipPx.Value) Then
                clipLogical = ToLogicalRect(clipPx.Value, dpi)
            End If

            child.Visible = True
            child.SetLayoutPlacementInternal(boundsLogical, clipLogical)
        End Sub

        Friend Shared Function ToLogicalRect(rectPx As SKRect,
                                             dpi As Single) As SKRect
            If dpi <= 0.01F OrElse Single.IsNaN(dpi) OrElse Single.IsInfinity(dpi) Then dpi = 1.0F
            Return New SKRect(rectPx.Left / dpi,
                              rectPx.Top / dpi,
                              rectPx.Right / dpi,
                              rectPx.Bottom / dpi)
        End Function

        Friend Shared Function IsUsableBounds(rect As SKRect) As Boolean
            Return Not rect.IsEmpty AndAlso
                   rect.Width > 1.0F AndAlso
                   rect.Height > 1.0F AndAlso
                   Not Single.IsNaN(rect.Left) AndAlso
                   Not Single.IsNaN(rect.Top) AndAlso
                   Not Single.IsNaN(rect.Right) AndAlso
                   Not Single.IsNaN(rect.Bottom)
        End Function

    End Class

End Namespace
