Option Strict On
Option Explicit On

Imports System

Namespace Nexamas.UI.CommandActions

     ''' <summary>
     ''' Internal command definition. One definition may be presented by button, menu, shortcut, toolbar, CommandBar, or CommandPalette.
     ''' </summary>
    Friend NotInheritable Class MASCommandDefinition

        Private ReadOnly _execute As Action(Of MASCommandExecutionContext)
        Private ReadOnly _canExecute As Func(Of MASCommandExecutionContext, Boolean)

        Friend Sub New(commandId As String,
                       text As String,
                       execute As Action(Of MASCommandExecutionContext),
                       Optional canExecute As Func(Of MASCommandExecutionContext, Boolean) = Nothing,
                       Optional shortcut As MASCommandShortcutGesture = Nothing,
                       Optional category As String = "",
                       Optional description As String = "")
            Dim id As String = MASCommandRegistry.NormalizeCommandId(commandId)
            If id.Length = 0 Then Throw New ArgumentException("A command id is required.", NameOf(commandId))
            If execute Is Nothing Then Throw New ArgumentNullException(NameOf(execute))

            Me.CommandId = id
            Me.Text = If(String.IsNullOrWhiteSpace(text), id, text.Trim())
            Me.Category = If(category, String.Empty).Trim()
            Me.Description = If(description, String.Empty).Trim()
            Me.Shortcut = If(shortcut, MASCommandShortcutGesture.Empty)
            _execute = execute
            _canExecute = canExecute
        End Sub

        Friend ReadOnly Property CommandId As String
        Friend ReadOnly Property Text As String
        Friend ReadOnly Property Category As String
        Friend ReadOnly Property Description As String
        Friend ReadOnly Property Shortcut As MASCommandShortcutGesture

        Friend ReadOnly Property HasShortcut As Boolean
            Get
                Return Shortcut IsNot Nothing AndAlso Not Shortcut.IsEmpty
            End Get
        End Property

        Friend ReadOnly Property HasCanExecuteHandler As Boolean
            Get
                Return _canExecute IsNot Nothing
            End Get
        End Property

        Friend Function CanExecute(context As MASCommandExecutionContext) As Boolean
            If _execute Is Nothing Then Return False
            If _canExecute Is Nothing Then Return True

            Return _canExecute.Invoke(If(context, New MASCommandExecutionContext(CommandId, MASCommandBindingSurfaceKind.Programmatic, String.Empty, Nothing)))
        End Function

        Friend Sub Execute(context As MASCommandExecutionContext)
            _execute.Invoke(If(context, New MASCommandExecutionContext(CommandId, MASCommandBindingSurfaceKind.Programmatic, String.Empty, Nothing)))
        End Sub

        Friend Function WithShortcut(shortcut As MASCommandShortcutGesture) As MASCommandDefinition
            Return New MASCommandDefinition(CommandId, Text, _execute, _canExecute, shortcut, Category, Description)
        End Function

        Friend Function ToCatalogEntry() As MASCommandCatalogEntry
            Dim shortcutText As String = If(HasShortcut, Shortcut.DisplayText, String.Empty)
            Return New MASCommandCatalogEntry(CommandId, Text, Category, Description, shortcutText, _execute IsNot Nothing, _canExecute IsNot Nothing)
        End Function

    End Class

End Namespace
