Option Strict On
Option Explicit On

Imports System

Namespace Nexamas.UI.FloatRuntime

    ' ============================================================
    ' MASFloatRuntime Contract
    ' Class: MASFloatHandle
    '
    ' Purpose:
    '   Represents the only public identity and control handle for an
    '   opened or opening Float instance.
    '
    ' Responsibility:
    '   Exposes stable public identity, lifecycle state, and a safe Close
    '   request method that routes back through runtime-owned policy and
    '   coordinator logic.
    '
    ' Owns:
    '   Public identity values.
    '   Public lifecycle state snapshot.
    '   Runtime-provided close request delegate.
    '
    ' Does Not Own:
    '   Host removal.
    '   Policy authorization.
    '   Result storage.
    '   Transition execution.
    '   Queue continuation.
    '   Session completion.
    '
    ' Allowed Dependencies:
    '   MASFloatSlot.
    '   MASFloatLayerLevel.
    '   MASFloatScope.
    '   MASFloatLifecycleState.
    '   MASFloatCloseReason.
    '   System.Func delegate.
    '
    ' Forbidden Dependencies:
    '   Legacy Overlay classes.
    '   OverlayManager.
    '   OverlayHost.
    '   OverlayContent.
    '   MASFloatHost.
    '   Public access to MASFloatCoordinator.
    '   Public access to MASFloatRuntimeState.
    '
    ' Lifecycle Role:
    '   Created by Coordinator when a request is accepted for opening.
    '   Used by callers to identify or request closing of a specific Float.
    '
    ' Threading:
    '   Public Close may be called by consumers.
    '   Runtime implementation behind the close delegate must marshal to UI
    '   thread if needed.
    '
    ' Mutation Rules:
    '   Public identity is immutable.
    '   State may be changed only by runtime internals through Friend members.
    '   External callers must not be able to mutate state or generation.
    '
    ' Invariants:
    '   No Float may be externally closed without a MASFloatHandle.
    '   No Feature Service may close by global current state.
    '   A stale handle or stale generation must never mutate a newer Float.
    '   Close must route through policy and coordinator.
    '
    ' Failure Rules:
    '   Close requests rejected by policy return False.
    '   A handle without a valid runtime close route returns False.
    ' ============================================================
    Friend NotInheritable Class MASFloatHandle

        Private ReadOnly _requestClose As Func(Of MASFloatHandle, MASFloatCloseReason, Boolean)

        Private _state As MASFloatLifecycleState

        Friend ReadOnly Property Id As Long

        Friend ReadOnly Property Generation As Long

        Friend ReadOnly Property FloatKey As String

        Friend ReadOnly Property OwnerKey As String

        Friend ReadOnly Property OwnerToken As MASFloatOwnerToken

        Friend ReadOnly Property Slot As MASFloatSlot

        Friend ReadOnly Property Layer As MASFloatLayerLevel

        Friend ReadOnly Property Scope As MASFloatScope

        Friend ReadOnly Property State As MASFloatState
            Get
                Return ToPublicState(_state)
            End Get
        End Property

        Friend ReadOnly Property LifecycleStateCore As MASFloatLifecycleState
            Get
                Return _state
            End Get
        End Property

        Friend ReadOnly Property IsOpen As Boolean
            Get
                Return _state = MASFloatLifecycleState.Open
            End Get
        End Property

        Friend ReadOnly Property IsClosing As Boolean
            Get
                Return _state = MASFloatLifecycleState.Closing
            End Get
        End Property

        Friend ReadOnly Property IsClosed As Boolean
            Get
                Return _state = MASFloatLifecycleState.Closed OrElse
                       _state = MASFloatLifecycleState.Disposed
            End Get
        End Property

        Friend Sub New(
            id As Long,
            generation As Long,
            floatKey As String,
            ownerKey As String,
            ownerToken As MASFloatOwnerToken,
            slot As MASFloatSlot,
            layer As MASFloatLayerLevel,
            scope As MASFloatScope,
            initialState As MASFloatLifecycleState,
            requestClose As Func(Of MASFloatHandle, MASFloatCloseReason, Boolean)
        )
            If id <= 0L Then
                Throw New ArgumentOutOfRangeException(NameOf(id))
            End If

            If generation <= 0L Then
                Throw New ArgumentOutOfRangeException(NameOf(generation))
            End If

            If String.IsNullOrWhiteSpace(floatKey) Then
                Throw New ArgumentException("FloatKey is required.", NameOf(floatKey))
            End If

            Dim normalizedOwnerToken As MASFloatOwnerToken = If(ownerToken, MASFloatOwnerToken.FromKey(ownerKey))
            ownerKey = normalizedOwnerToken.Key

            Me.Id = id
            Me.Generation = generation
            Me.FloatKey = floatKey
            Me.OwnerKey = ownerKey
            Me.OwnerToken = normalizedOwnerToken
            Me.Slot = slot
            Me.Layer = layer
            Me.Scope = scope
            _state = initialState
            _requestClose = requestClose
        End Sub

        Friend Function Close(
            Optional reason As MASFloatCloseReason = MASFloatCloseReason.Programmatic
        ) As Boolean
            If _requestClose Is Nothing Then
                Return False
            End If

            Return _requestClose(Me, reason)
        End Function

        Friend Sub SetState(state As MASFloatLifecycleState)
            _state = state
        End Sub

        Private Shared Function ToPublicState(state As MASFloatLifecycleState) As MASFloatState
            Select Case state
                Case MASFloatLifecycleState.Requested
                    Return MASFloatState.Requested
                Case MASFloatLifecycleState.Opening
                    Return MASFloatState.Opening
                Case MASFloatLifecycleState.Open
                    Return MASFloatState.Open
                Case MASFloatLifecycleState.Closing
                    Return MASFloatState.Closing
                Case MASFloatLifecycleState.Closed
                    Return MASFloatState.Closed
                Case MASFloatLifecycleState.Disposed
                    Return MASFloatState.Disposed
                Case Else
                    Return MASFloatState.Closed
            End Select
        End Function

        Public Overrides Function ToString() As String
            Return String.Format(
                Globalization.CultureInfo.InvariantCulture,
                "MASFloatHandle(Id={0}, Generation={1}, FloatKey={2}, OwnerKey={3}, Slot={4}, Layer={5}, Scope={6}, State={7})",
                Me.Id,
                Me.Generation,
                Me.FloatKey,
                Me.OwnerKey,
                Me.Slot,
                Me.Layer,
                Me.Scope,
                Me.State
            )
        End Function

    End Class

End Namespace