Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports System.Windows.Forms
Imports Nexamas.UI.Theming
Imports SkiaSharp

Namespace Nexamas.UI.FloatRuntime

    ' <summary>
    ' Contains Float routing lookup, ordering, capture, and visual-state helpers separated from public input event routing.
    ' </summary>
    Partial Friend NotInheritable Class MASFloatInputRouter

        Private Function FindEscapeCloseHandle() As MASFloatHandle
            Dim record As MASFloatLifecycleRecord = FindTopKeyboardRecord()

            If record Is Nothing Then
                Return Nothing
            End If

            Dim policy As IMASFloatInputPolicy = GetInputPolicy(record)

            If policy Is Nothing Then
                Return Nothing
            End If

            If Not HasCapability(record, MASFloatCapabilities.KeyboardInput) OrElse
               Not policy.AcceptsKeyboardInput Then
                Return Nothing
            End If

            If Not HasCapability(record, MASFloatCapabilities.EscapeDismiss) OrElse
               Not policy.CloseOnEscape Then
                Return Nothing
            End If

            Return record.Handle
        End Function

        Private Function PrepareOutsidePointerToTopRecord() As OutsidePointerWork
            Dim record As MASFloatLifecycleRecord = FindTopPointerRecord()

            If record Is Nothing Then
                Return Nothing
            End If

            Return PrepareOutsidePointerToRecord(record)
        End Function

        Private Function PrepareOutsidePointerToRecord(
            record As MASFloatLifecycleRecord
        ) As OutsidePointerWork
            If record Is Nothing Then
                Return Nothing
            End If

            Dim policy As IMASFloatInputPolicy = GetInputPolicy(record)

            If policy Is Nothing Then
                Return Nothing
            End If

            Dim shouldClose As Boolean =
                policy.CloseOnOutsidePointer AndAlso
                HasCapability(record, MASFloatCapabilities.OutsideDismiss)

            Return New OutsidePointerWork() With {
                .Handle = record.Handle,
                .ShouldClose = shouldClose,
                .Swallow = policy.SwallowOutsidePointer,
                .AllowPointerThroughAfterClose = AllowsPointerThroughAfterOutsideClose(record, policy)
            }
        End Function

        Private Shared Function AllowsPointerThroughAfterOutsideClose(record As MASFloatLifecycleRecord,
                                                                     policy As IMASFloatInputPolicy) As Boolean
            If record Is Nothing OrElse policy Is Nothing Then Return False
            If policy.SwallowOutsidePointer Then Return False
            If record.ResolvedRequest Is Nothing OrElse record.ResolvedRequest.Descriptor Is Nothing Then Return False

            Return String.Equals(
                record.ResolvedRequest.Descriptor.Key,
                MASFloatKeys.MenuBarDropDownMenu,
                StringComparison.Ordinal)
        End Function

        Private Function ExecuteOutsidePointerWork(work As OutsidePointerWork) As Boolean
            If work Is Nothing Then
                Return False
            End If

            If Not work.ShouldClose Then
                Return work.Swallow
            End If

            Dim closed As Boolean =
                _coordinator.Close(
                    work.Handle,
                    MASFloatCloseReason.OutsidePointer,
                    requestedBySession:=False
                )

            If closed Then
                ReleasePointerCaptureIfSame(work.Handle)

                ' MenuBar dropdowns intentionally opt out of swallowing outside clicks so
                ' one click can close the current menu and activate/hover another shell menu item.
                If work.AllowPointerThroughAfterClose Then Return False

                Return True
            End If

            Return work.Swallow
        End Function


    End Class

End Namespace
