Option Strict On
Option Explicit On

Imports SkiaSharp

Namespace Nexamas.UI.FloatRuntime

    ' ============================================================
    ' MASFloatRuntime Contract
    ' Class: MASFloatHost
    '
    ' Purpose:
    '   Provides the new visual hosting foundation for MASFloatRuntime.
    '
    ' Responsibility:
    '   Owns MASFloatHostState, accepts already-authorized lifecycle records
    '   for hosting, stores their resolved pixel-space bounds, and exposes
    '   host invalidation requests through a clean event.
    '
    ' Owns:
    '   MASFloatHostState.
    '   MASFloatPresentationEngine.
    '   Host available pixel-space bounds.
    '
    ' Does Not Own:
    '   Descriptor registration.
    '   Show policy.
    '   Close policy.
    '   Lifecycle state transitions.
    '   Queue state.
    '   Result delivery.
    '   Transition execution.
    '   Input routing.
    '   Focus ownership.
    '   ThemeContext.
    '   Nexamas UI root host.
    '
    ' Allowed Dependencies:
    '   MASFloatHostState.
    '   MASFloatPresentationEngine.
    '   MASFloatLifecycleRecord.
    '   MASFloatResolvedRequest.
    '   MASFloatHandle.
    '   SkiaSharp.SKRect.
    '
    ' Forbidden Dependencies:
    '   Legacy Overlay classes.
    '   OverlayHost.
    '   OverlayManager.
    '   OverlayContent.
    '   OverlayLayer.
    '   OverlayService.
    '   BlockingControlsOverlayContent.
    '   Feature-owned lifecycle services.
    '
    ' Lifecycle Role:
    '   Host is called by Coordinator after policy approval and before/after
    '   lifecycle state transitions.
    '   Host does not approve lifecycle transitions by itself.
    '
    ' Threading:
    '   Must be accessed on the UI thread by runtime-owned lifecycle flow.
    '   Host itself does not perform random UI marshaling.
    '
    ' Mutation Rules:
    '   Hosted records are added or removed only through runtime-owned flow.
    '   Bounds are always pixel-space.
    '   Invalidation is requested through RequestInvalidated event, allowing
    '   Nexamas UI integration without depending on legacy Overlay.
    '
    ' Invariants:
    '   MASFloatHost is the new visual hosting infrastructure.
    '   It must not inherit from or depend on legacy OverlayHost.
    '   Host state identity uses Id + Generation.
    '
    ' Failure Rules:
    '   Missing records are rejected.
    '   Removing a missing handle returns False.
    ' ============================================================
    Friend NotInheritable Class MASFloatHost

        Private ReadOnly _state As New MASFloatHostState()

        Private ReadOnly _presentationEngine As New MASFloatPresentationEngine()

        Friend Event Invalidated As EventHandler

        Friend ReadOnly Property State As MASFloatHostState
            Get
                Return _state
            End Get
        End Property

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

        Friend Sub SetAvailableBoundsPx(availableBoundsPx As SKRect)
            If SameRectPx(_state.AvailableBoundsPx, availableBoundsPx) Then
                Return
            End If

            _state.AvailableBoundsPx = availableBoundsPx
            RequestInvalidate()
        End Sub

        Friend Function AddRecord(record As MASFloatLifecycleRecord) As SKRect
            If record Is Nothing Then
                Throw New ArgumentNullException(NameOf(record))
            End If

            Dim boundsPx As SKRect =
                _presentationEngine.ResolveBoundsPx(
                    record.ResolvedRequest,
                    _state.AvailableBoundsPx
                )

            _state.AddRecord(record, boundsPx)
            RequestInvalidate()

            Return boundsPx
        End Function

        Friend Function RemoveRecord(handle As MASFloatHandle) As Boolean
            Dim removed As Boolean = _state.RemoveRecord(handle)

            If removed Then
                RequestInvalidate()
            End If

            Return removed
        End Function

        Friend Function TryGetBoundsPx(
            handle As MASFloatHandle,
            ByRef boundsPx As SKRect
        ) As Boolean
            Return _state.TryGetBoundsPx(handle, boundsPx)
        End Function

        Friend Function TrySetBoundsPx(
            handle As MASFloatHandle,
            boundsPx As SKRect
        ) As Boolean
            Dim currentBoundsPx As SKRect = SKRect.Empty
            If _state.TryGetBoundsPx(handle, currentBoundsPx) AndAlso
               SameRectPx(currentBoundsPx, boundsPx) Then

                Return False
            End If

            Dim changed As Boolean = _state.TrySetBoundsPx(handle, boundsPx)

            If changed Then
                RequestInvalidate()
            End If

            Return changed
        End Function

        Friend Sub Clear()
            _state.Clear()
            RequestInvalidate()
        End Sub

        Friend Sub RequestInvalidate()
            RaiseEvent Invalidated(Me, EventArgs.Empty)
        End Sub

        Private Shared Function SameRectPx(left As SKRect, right As SKRect) As Boolean
            Const epsilon As Single = 0.01F

            Return Math.Abs(left.Left - right.Left) <= epsilon AndAlso
                   Math.Abs(left.Top - right.Top) <= epsilon AndAlso
                   Math.Abs(left.Right - right.Right) <= epsilon AndAlso
                   Math.Abs(left.Bottom - right.Bottom) <= epsilon
        End Function

    End Class

End Namespace
