Option Strict On
Option Explicit On

Imports System
Imports Nexamas.UI.Motion
Imports System.Windows.Forms
Imports Nexamas.UI.Theming
Imports SkiaSharp

Namespace Nexamas.UI.FloatRuntime

    ' ============================================================
    ' MASFloatRuntime Contract
    ' Class: MASFloatRuntime
    '
    ' Purpose:
    '   Provides the official public facade for the new MASFloatRuntime
    '   floating UI system.
    '
    ' Responsibility:
    '   Exposes direct public APIs for registering Float types, showing
    '   Float requests, closing by handle, closing by owner, querying open
    '   state, configuring available host bounds, and forwarding host
    '   invalidation requests to Nexamas UI integration.
    '
    ' Owns:
    '   MASFloatRegistry.
    '   MASFloatRuntimeState.
    '   MASFloatPolicyEngine.
    '   MASFloatHost.
    '   MASFloatTransitionEngine.
    '   MASFloatFocusManager.
    '   MASFloatCoordinator.
    '   MASFloatInputRouter.
    '
    ' Does Not Own:
    '   Legacy Overlay infrastructure.
    '   Feature-owned lifecycle services.
    '   Nexamas UI rendering surface.
    '   ThemeContext.
    '   Actual UI-thread dispatcher implementation in v1.
    '
    ' Allowed Dependencies:
    '   MASFloatRegistry.
    '   MASFloatRuntimeState.
    '   MASFloatPolicyEngine.
    '   MASFloatHost.
    '   MASFloatTransitionEngine.
    '   MASFloatFocusManager.
    '   MASFloatCoordinator.
    '   MASFloatInputRouter.
    '   MASFloatRequest.
    '   MASFloatHandle.
    '   MASFloatCloseReason.
    '   SkiaSharp.SKRect.
    '   System.Windows.Forms.MouseButtons.
    '   System.Windows.Forms.Keys.
    '
    ' Forbidden Dependencies:
    '   Legacy Overlay classes.
    '   OverlayHost.
    '   OverlayManager.
    '   OverlayContent.
    '   OverlayLayer.
    '   OverlayService.
    '   BlockingControlsOverlayContent.
    '   MASFilePickerOverlayService.
    '   MASOverlayPanelService.
    '   MessageBoxOverlayService.
    '   MASFileExplorerOverlayService.
    '   DropDownMenuPopupService.
    '   Wrapper or Launcher lifecycle ownership.
    '
    ' Lifecycle Role:
    '   Public entry point.
    '   Delegates lifecycle orchestration to MASFloatCoordinator.
    '   Does not bypass Registry, PolicyEngine, Coordinator, Session, Host,
    '   or Result rules.
    '
    ' Threading:
    '   v1 assumes the caller enters on the UI/runtime path.
    '   Future Nexamas UI integration may inject a UI dispatcher/marshaler
    '   here without changing consumer API.
    '
    ' Mutation Rules:
    '   External consumers may use Registry for descriptor registration.
    '   External consumers may show/close only through this facade or through
    '   MASFloatHandle.Close.
    '   Internal runtime state is never exposed publicly.
    '
    ' Invariants:
    '   No unregistered Float may be shown.
    '   No external global CloseCurrent API exists.
    '   No Feature service owns lifecycle.
    '   No external result event before Closed.
    '   No legacy Overlay dependency exists inside MASFloatRuntime.
    '
    ' Failure Rules:
    '   Invalid requests throw through Coordinator/Registry validation.
    '   Close returns False when handle is missing, stale, rejected, or closed.
    ' ============================================================
    Friend NotInheritable Class MASFloatRuntime
        Implements IDisposable

        Private ReadOnly _registry As MASFloatRegistry
        Private ReadOnly _state As MASFloatRuntimeState
        Private ReadOnly _policy As MASFloatPolicyEngine
        Private ReadOnly _host As MASFloatHost
        Private ReadOnly _transitionEngine As MASFloatTransitionEngine
        Private ReadOnly _focusManager As MASFloatFocusManager
        Private ReadOnly _coordinator As MASFloatCoordinator
        Private ReadOnly _inputRouter As MASFloatInputRouter
        Private ReadOnly _presenter As MASFloatHostPresenter

        Private _disposed As Boolean

        Friend Event Invalidated As EventHandler

        Friend Sub New(Optional motionFrameClock As MASMotionFrameClock = Nothing,
                       Optional postToUiThread As Func(Of Action, Boolean) = Nothing)
            _registry = New MASFloatRegistry()
            _state = New MASFloatRuntimeState()
            _policy = New MASFloatPolicyEngine()
            _host = New MASFloatHost()
            _presenter = New MASFloatHostPresenter()
            _transitionEngine = New MASFloatTransitionEngine(AddressOf _host.RequestInvalidate, motionFrameClock)
            _focusManager = New MASFloatFocusManager()

            _coordinator = New MASFloatCoordinator(
                _registry,
                _state,
                _policy,
                _host,
                _transitionEngine,
                _focusManager,
                postToUiThread:=postToUiThread
            )

            _inputRouter = New MASFloatInputRouter(
                _coordinator,
                _state,
                _host,
                _focusManager
            )

            AddHandler _host.Invalidated, AddressOf OnHostInvalidated
        End Sub

        ''' <summary>
        ''' Advanced extension registry for custom Float descriptors.
        ''' Normal application code should prefer MASApplicationWindow.Services and MASApplicationWindow.Shell.
        ''' </summary>
        Friend ReadOnly Property Registry As MASFloatRegistry
            Get
                Return _registry
            End Get
        End Property

        Friend ReadOnly Property AvailableBoundsPx As SKRect
            Get
                Return _host.AvailableBoundsPx
            End Get
        End Property

        Friend ReadOnly Property InputRouter As MASFloatInputRouter
            Get
                Return _inputRouter
            End Get
        End Property

        Friend ReadOnly Property Host As MASFloatHost
            Get
                Return _host
            End Get
        End Property

        Friend ReadOnly Property FocusManager As MASFloatFocusManager
            Get
                Return _focusManager
            End Get
        End Property

        Friend Sub SetAvailableBoundsPx(availableBoundsPx As SKRect)
            _host.SetAvailableBoundsPx(availableBoundsPx)
        End Sub

        ''' <summary>
        ''' Registers the built-in MAS Float descriptors into this runtime.
        ''' RootHost calls this during composition; external callers should only use it for advanced host scenarios.
        ''' </summary>
        Friend Sub RegisterDefaultFloats()
            MASFloatBootstrap.RegisterDefaultFloats(_registry)
        End Sub

        ''' <summary>
        ''' Shows a raw Float request through the advanced runtime facade.
        ''' Prefer typed window facades such as Services.Dialogs, Services.Toasts, Services.Tooltips, and Shell menus.
        ''' </summary>
        Friend Function Show(request As MASFloatRequest) As MASFloatHandle
            If _disposed Then Return Nothing

            Nexamas.UI.Performance.MASPerformanceSystem.RecordConsumerStateRefresh(
                Nexamas.UI.Performance.MASPerformanceConsumerKind.FloatRuntime,
                "MASFloatRuntime.Show")
            Return _coordinator.Show(request)
        End Function

        Friend Function ShowEx(request As MASFloatRequest) As MASFloatShowResult
            If _disposed Then Return MASFloatShowResult.Rejected("Float runtime is disposed.")

            Nexamas.UI.Performance.MASPerformanceSystem.RecordConsumerStateRefresh(
                Nexamas.UI.Performance.MASPerformanceConsumerKind.FloatRuntime,
                "MASFloatRuntime.ShowEx")
            Return _coordinator.ShowEx(request)
        End Function

        Friend Function Close(
            handle As MASFloatHandle,
            Optional reason As MASFloatCloseReason = MASFloatCloseReason.Programmatic
        ) As Boolean
            If _disposed Then Return False

            Nexamas.UI.Performance.MASPerformanceSystem.RecordConsumerStateRefresh(
                Nexamas.UI.Performance.MASPerformanceConsumerKind.FloatRuntime,
                "MASFloatRuntime.Close")
            Return _coordinator.Close(
                handle,
                reason,
                requestedBySession:=False
            )
        End Function

        Friend Function CloseByOwner(
            ownerKey As String,
            Optional reason As MASFloatCloseReason = MASFloatCloseReason.Programmatic
        ) As Integer
            If _disposed Then Return 0
            Return _coordinator.CloseByOwner(ownerKey, reason)
        End Function

        Friend Function IsOpen(handle As MASFloatHandle) As Boolean
            If _disposed Then Return False
            Return _coordinator.IsOpen(handle)
        End Function

        Friend Sub Render(canvas As SKCanvas, ctx As MASThemeContext)
            If _disposed Then Return
            _presenter.Render(_host, canvas, ctx)
        End Sub

        Friend Function HasAnyFloatVisual() As Boolean
            If _disposed Then Return False
            Return _inputRouter.HasAnyFloatVisual()
        End Function

        Friend Function HasInteractiveFloat() As Boolean
            If _disposed Then Return False
            Return _inputRouter.HasInteractiveFloat()
        End Function

        Friend Function HasBlockingFloat() As Boolean
            If _disposed Then Return False
            Return _inputRouter.HasBlockingFloat()
        End Function

        Friend Function IsPointerOwnedByFloat(
            ctx As MASThemeContext,
            ptPx As SKPoint
        ) As Boolean
            If _disposed Then Return False
            Return _inputRouter.IsPointerOwnedByFloat(ctx, ptPx)
        End Function

        Friend Function RoutePointerMove(
            ctx As MASThemeContext,
            ptPx As SKPoint
        ) As MASFloatPointerMoveRoutingResult
            If _disposed Then Return MASFloatPointerMoveRoutingResult.NotHandled()

            Nexamas.UI.Performance.MASPerformanceSystem.RecordConsumerInput(
                Nexamas.UI.Performance.MASPerformanceConsumerKind.FloatRuntime,
                "MASFloatRuntime.RoutePointerMove")
            Return _inputRouter.RoutePointerMove(ctx, ptPx)
        End Function

        Friend Function RoutePointerDown(
            ctx As MASThemeContext,
            ptPx As SKPoint,
            button As MouseButtons
        ) As Boolean
            If _disposed Then Return False

            Nexamas.UI.Performance.MASPerformanceSystem.RecordConsumerInput(
                Nexamas.UI.Performance.MASPerformanceConsumerKind.FloatRuntime,
                "MASFloatRuntime.RoutePointerDown")
            Return _inputRouter.RoutePointerDown(ctx, ptPx, button)
        End Function

        Friend Function RoutePointerUp(
            ctx As MASThemeContext,
            ptPx As SKPoint,
            button As MouseButtons
        ) As Boolean
            If _disposed Then Return False
            Return _inputRouter.RoutePointerUp(ctx, ptPx, button)
        End Function

        Friend Function RoutePointerWheel(
            ctx As MASThemeContext,
            ptPx As SKPoint,
            delta As Integer
        ) As Boolean
            If _disposed Then Return False

            Nexamas.UI.Performance.MASPerformanceSystem.RecordConsumerInput(
                Nexamas.UI.Performance.MASPerformanceConsumerKind.FloatRuntime,
                "MASFloatRuntime.RoutePointerWheel")
            Return _inputRouter.RoutePointerWheel(ctx, ptPx, delta)
        End Function

        Friend Function RouteKeyDown(
            ctx As MASThemeContext,
            keyCode As Keys
        ) As Boolean
            If _disposed Then Return False
            Return _inputRouter.RouteKeyDown(ctx, keyCode)
        End Function

        Friend Function RouteKeyUp(
            ctx As MASThemeContext,
            keyCode As Keys
        ) As Boolean
            If _disposed Then Return False
            Return _inputRouter.RouteKeyUp(ctx, keyCode)
        End Function

        Friend Function RouteTextInput(
            ctx As MASThemeContext,
            text As String
        ) As Boolean
            If _disposed Then Return False
            Return _inputRouter.RouteTextInput(ctx, text)
        End Function

        Friend Function RouteWin32ImeMessage(
            ctx As MASThemeContext,
            hwnd As IntPtr,
            message As Integer,
            wParam As IntPtr,
            lParam As IntPtr
        ) As Boolean
            If _disposed Then Return False
            Return _inputRouter.RouteWin32ImeMessage(ctx, hwnd, message, wParam, lParam)
        End Function

        Friend Sub HostLostFocus()
            If _disposed Then Return
            _inputRouter.HostLostFocus()
        End Sub

        Friend Function RouteEscapeKey() As Boolean
            If _disposed Then Return False
            Return _inputRouter.RouteEscapeKey()
        End Function

        Friend Function RouteOutsidePointerForSlot(slot As MASFloatSlot) As Boolean
            If _disposed Then Return False
            Return _inputRouter.RouteOutsidePointerForSlot(slot)
        End Function

        Friend Function RouteOutsidePointerToHandle(handle As MASFloatHandle) As Boolean
            If _disposed Then Return False
            Return _inputRouter.RouteOutsidePointerToHandle(handle)
        End Function

        Friend Sub Shutdown()
            If _disposed Then Return

            Try
                _coordinator.Shutdown()
            Catch masCaughtException1 As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDisposeCleanup(
                    masCaughtException1,
                    "MASFloatRuntime.Shutdown")
            End Try
        End Sub

        Public Sub Dispose() Implements IDisposable.Dispose
            If _disposed Then Return

            Try
                RemoveHandler _host.Invalidated, AddressOf OnHostInvalidated
            Catch masCaughtException2 As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDisposeCleanup(
                    masCaughtException2,
                    "MASFloatRuntime.Dispose.RemoveHostHandler")
            End Try

            Try
                _coordinator.Shutdown()
            Catch masCaughtException3 As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDisposeCleanup(
                    masCaughtException3,
                    "MASFloatRuntime.Dispose.Shutdown")
            End Try

            _disposed = True
        End Sub

        Private Sub OnHostInvalidated(sender As Object, e As EventArgs)
            Try
                RaiseEvent Invalidated(Me, EventArgs.Empty)
            Catch masCaughtException1 As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowDiagnosticOnly(
                    masCaughtException1,
                    "MASFloatRuntime.Invalidated")
            End Try
        End Sub

    End Class

End Namespace
