Option Strict On
Option Explicit On

Imports System

Namespace Nexamas.UI.Architecture

    ''' <summary>
    ''' Contract-driven focus authority for MAS runtime components.
    ''' FocusRole is the authority. ControlsLayer, overlays, and renderers may consume
    ''' this resolver, but must not invent focus eligibility locally.
    ''' </summary>
    Friend NotInheritable Class MASFocusResolver

        Private Sub New()
        End Sub

        Friend Shared Function CanReceiveKeyboardFocus(contract As MASResolvedComponentContract) As Boolean

            If contract Is Nothing Then
                Throw New ArgumentNullException(NameOf(contract))
            End If

            contract.AssertConsumable()

            Return MASFocusContractRegistry.IsFocusableRole(contract.FocusRole) AndAlso
                   contract.Supports(MASCapability.Focusable)

        End Function

        Friend Shared Function CanReceivePointerFocus(contract As MASResolvedComponentContract) As Boolean

            If Not CanReceiveKeyboardFocus(contract) Then
                Return False
            End If

            Return contract.InputRole = MASInputRole.PointerOnly OrElse
                   contract.InputRole = MASInputRole.PointerAndKeyboard OrElse
                   contract.InputRole = MASInputRole.TextInput OrElse
                   contract.InputRole = MASInputRole.IMETextInput

        End Function

        Friend Shared Function IsFocusScope(contract As MASResolvedComponentContract) As Boolean

            If contract Is Nothing Then
                Throw New ArgumentNullException(NameOf(contract))
            End If

            Return contract.FocusRole = MASFocusRole.FocusScope OrElse
                   contract.FocusRole = MASFocusRole.ModalFocusScope

        End Function

        Friend Shared Function IsModalFocusScope(contract As MASResolvedComponentContract) As Boolean

            If contract Is Nothing Then
                Throw New ArgumentNullException(NameOf(contract))
            End If

            Return contract.FocusRole = MASFocusRole.ModalFocusScope

        End Function

        Friend Shared Function RequiresFocusRing(contract As MASResolvedComponentContract) As Boolean

            If contract Is Nothing Then
                Throw New ArgumentNullException(NameOf(contract))
            End If

            contract.AssertConsumable()

            Return MASFocusContractRegistry.IsFocusableRole(contract.FocusRole) AndAlso
                   contract.HasLayer(MASRenderLayer.Focus)

        End Function

        Friend Shared Function ValidateDescriptor(descriptor As MASComponentDescriptor,
                                                  resolved As MASResolvedComponentContract,
                                                  typeName As String) As String

            If descriptor Is Nothing Then
                Return "- Focus validation received a null descriptor."
            End If

            If resolved Is Nothing Then
                Return "- Focus validation received a null resolved contract for " & typeName
            End If

            If Not MASFocusContractRegistry.IsSupported(descriptor.FocusRole) Then
                Return "- Unsupported FocusRole for " & typeName & ": " & descriptor.FocusRole.ToString()
            End If

            If Not MASFocusContractRegistry.AllowsInputRole(descriptor.InputRole, descriptor.FocusRole) Then
                Return "- Keyboard-capable component has no valid focus contract: " & typeName
            End If

            If Not MASFocusContractRegistry.AllowsTextInputRole(descriptor.InputRole, descriptor.FocusRole) Then
                Return "- Text input must use Focusable or FocusScope: " & typeName
            End If

            If Not MASFocusContractRegistry.AllowsModalScope(
                descriptor.Category,
                descriptor.OverlayRole,
                descriptor.FocusRole) Then

                Return "- ModalFocusScope is only legal for modal overlay/dialog/shell contracts: " & typeName
            End If

            If Not MASFocusContractRegistry.AllowsFocusVisual(
                descriptor.FocusRole,
                resolved.RenderProfile) Then

                Return "- FocusRole is declared but RenderProfile has no Focus layer for " & typeName
            End If

            If Not MASFocusContractRegistry.AllowsFocusCapability(
                descriptor.FocusRole,
                resolved.Capabilities) Then

                Return "- FocusRole is declared but capabilities do not include Focusable for " & typeName
            End If

            Return Nothing

        End Function

    End Class

End Namespace