Option Strict On
Option Explicit On

Namespace Nexamas.UI.Architecture

    ''' <summary>
    ''' Declares legal focus contracts for MAS runtime components.
    ''' This registry validates focus eligibility only. It does not move focus,
    ''' draw focus rings, or read live keyboard/pointer state.
    ''' </summary>
    Friend NotInheritable Class MASFocusContractRegistry

        Private Sub New()
        End Sub

        Friend Shared Function IsFocusableRole(role As MASFocusRole) As Boolean
            Return role = MASFocusRole.Focusable OrElse
                   role = MASFocusRole.FocusScope OrElse
                   role = MASFocusRole.ModalFocusScope
        End Function

        Friend Shared Function IsSupported(role As MASFocusRole) As Boolean
            Select Case role
                Case MASFocusRole.None,
                     MASFocusRole.NotFocusable,
                     MASFocusRole.Focusable,
                     MASFocusRole.FocusScope,
                     MASFocusRole.ModalFocusScope

                    Return True

                Case Else
                    Return False
            End Select
        End Function

        Friend Shared Function RequiresKeyboardFocus(inputRole As MASInputRole) As Boolean
            Return inputRole = MASInputRole.KeyboardOnly OrElse
                   inputRole = MASInputRole.PointerAndKeyboard OrElse
                   inputRole = MASInputRole.TextInput OrElse
                   inputRole = MASInputRole.IMETextInput OrElse
                   inputRole = MASInputRole.RoutedContainer
        End Function

        Friend Shared Function RequiresTextFocus(inputRole As MASInputRole) As Boolean
            Return inputRole = MASInputRole.TextInput OrElse
                   inputRole = MASInputRole.IMETextInput
        End Function

        Friend Shared Function AllowsInputRole(inputRole As MASInputRole,
                                               focusRole As MASFocusRole) As Boolean

            If Not RequiresKeyboardFocus(inputRole) Then
                Return True
            End If

            Return IsFocusableRole(focusRole)

        End Function

        Friend Shared Function AllowsTextInputRole(inputRole As MASInputRole,
                                                   focusRole As MASFocusRole) As Boolean

            If Not RequiresTextFocus(inputRole) Then
                Return True
            End If

            Return focusRole = MASFocusRole.Focusable OrElse
                   focusRole = MASFocusRole.FocusScope

        End Function

        Friend Shared Function AllowsModalScope(category As MASComponentCategory,
                                                overlayRole As MASOverlayRole,
                                                focusRole As MASFocusRole) As Boolean

            If focusRole <> MASFocusRole.ModalFocusScope Then
                Return True
            End If

            If overlayRole = MASOverlayRole.Dialog OrElse
               overlayRole = MASOverlayRole.Blocking Then

                Return True
            End If

            Select Case category
                Case MASComponentCategory.OverlayContent,
         MASComponentCategory.DialogContent,
         MASComponentCategory.Shell,
         MASComponentCategory.FloatContent

                    Return True

                Case Else
                    Return False
            End Select

        End Function

        Friend Shared Function AllowsFocusVisual(focusRole As MASFocusRole,
                                                 renderProfile As MASRenderProfile) As Boolean

            If Not IsFocusableRole(focusRole) Then
                Return True
            End If

            If renderProfile Is Nothing Then
                Return False
            End If

            Return renderProfile.HasLayer(MASRenderLayer.Focus)

        End Function

        Friend Shared Function AllowsFocusCapability(focusRole As MASFocusRole,
                                                     capabilities As MASCapabilitySet) As Boolean

            If Not IsFocusableRole(focusRole) Then
                Return True
            End If

            Return capabilities.Supports(MASCapability.Focusable)

        End Function

    End Class

End Namespace