Option Strict On
Option Explicit On

Imports System
Imports Nexamas.UI.Controls
Imports Nexamas.UI.FloatRuntime
Imports Nexamas.UI.Host
Imports SkiaSharp

Namespace Nexamas.UI.Application

    ''' <summary>
    ''' Official MASApplicationWindow facade for compact floating operation progress.
    ''' The facade hosts the real MASOperationProgressBox inside the root FloatRuntime directly;
    ''' it does not create a PanelShell dialog, a local overlay, or a hand-drawn progress surface.
    ''' </summary>
    Public NotInheritable Class MASApplicationWindowProgress

        Private Const ProgressLaneOwnerKey As String = "MAS.Application.Progress"

        Private ReadOnly _rootHost As MASSkiaRootHost

        Private ReadOnly Property RootHost As MASSkiaRootHost
            Get
                _rootHost.ThrowIfDisposedCore()
                Return _rootHost
            End Get
        End Property

        Friend Sub New(rootHost As MASSkiaRootHost)
            If rootHost Is Nothing Then Throw New ArgumentNullException(NameOf(rootHost))
            _rootHost = rootHost
        End Sub

        Public Function ShowOperation(titleText As String,
                                      statusText As String,
                                      Optional percent As Double = 0.0R,
                                      Optional ownerKey As String = "MAS.Application.Progress") As MASApplicationProgressHandle
            Dim root As MASSkiaRootHost = RootHost

            Dim progressBox As MASOperationProgressBox = MASOperationProgressBox.Create(
                titleText:=If(titleText, String.Empty),
                statusText:=If(statusText, String.Empty)).WithPercent(percent)

            Dim content As New MASFloatControlsContent(
                name:="MAS.Application.Progress.FloatContent",
                themeHost:=root.ThemeHostCore,
                invalidate:=AddressOf root.RequestInvalidate)

            content.AcceptsPointerInput = False
            content.AcceptsKeyboardInput = False
            content.AcceptsTextInput = False
            content.CloseOnEscape = False
            content.CloseOnOutsidePointer = False
            content.SwallowOutsidePointer = False
            content.Add(progressBox)

            Dim availablePx As SKRect = root.GetSurfaceViewportPx()
            Dim boundsPx As SKRect = ResolveProgressBoundsPx(availablePx, root.GetDpi())

            ' Operation progress is a single root-owned float lane. The optional ownerKey
            ' argument is preserved for caller compatibility, but FloatRuntime ownership stays
            ' stable so CloseSameOwnerThenShow can replace only the progress float it owns.
            Dim request As New MASFloatRequest() With {
                .FloatKey = MASFloatKeys.Progress,
                .OwnerKey = ProgressLaneOwnerKey,
                .Content = content,
                .RequestedSlot = MASFloatSlot.System,
                .RequestedScope = MASFloatScope.Owner,
                .RequestedLayer = MASFloatLayerLevel.Passive,
                .RequestedPresentation = MASFloatPresentationProfiles.Progress(),
                .ShowPolicy = MASFloatShowPolicy.CloseSameOwnerThenShow,
                .InitialBoundsPx = boundsPx,
                .AvailableBoundsPx = availablePx,
                .Shield = MASFloatShieldOptions.None
            }

            Dim showResult As MASFloatShowResult = root.FloatRuntimeCore.ShowEx(request)
            If showResult Is Nothing OrElse showResult.Status = MASFloatShowStatus.Rejected OrElse showResult.Handle Is Nothing Then
                content.Dispose()
                Throw New InvalidOperationException("MAS operation progress float was rejected: " & If(showResult Is Nothing, "No result", showResult.Reason))
            End If

            root.PresentFrameNow()

            Return New MASApplicationProgressHandle(root, showResult.Handle, content, progressBox)
        End Function

        Private Shared Function ResolveProgressBoundsPx(availablePx As SKRect, dpi As Single) As SKRect
            If dpi <= 0.0F OrElse Single.IsNaN(dpi) OrElse Single.IsInfinity(dpi) Then dpi = 1.0F

            Dim widthPx As Single = 520.0F * dpi
            Dim heightPx As Single = 132.0F * dpi

            If Not availablePx.IsEmpty AndAlso availablePx.Width > 1.0F AndAlso availablePx.Height > 1.0F Then
                widthPx = Math.Min(widthPx, availablePx.Width - (32.0F * dpi))
                heightPx = Math.Min(heightPx, availablePx.Height - (32.0F * dpi))
                Dim left As Single = availablePx.Left + ((availablePx.Width - widthPx) / 2.0F)
                Dim top As Single = availablePx.Top + ((availablePx.Height - heightPx) / 2.0F)
                Return New SKRect(left, top, left + widthPx, top + heightPx)
            End If

            Return New SKRect(0.0F, 0.0F, widthPx, heightPx)
        End Function
    End Class

End Namespace
