' *
' * The project site is at: http://sourceforge.jp/projects/fishbornas/
' *
' * First author tiritomato 2012.
' *
' * Distributed under the FishbornArchiveShelf License (See
' *  file "Licenses/License.txt" contained in a project, or the following link.
' *  http://sourceforge.jp/projects/fishbornas/scm/svn/blobs/head/trunk/Licenses/License.txt)
' *
' * 2012.06.07 Initial Revision (tiritomato)
' *

Public MustInherit Class CustomContextMenu
    Inherits Windows.Forms.ContextMenuStrip

    Private ItemOnClick As EventHandler

    Public Shadows Sub Show(ByVal Control As Windows.Forms.Control, Optional ByVal TextBox As TextBox = Nothing, Optional ByVal ItemOnClick As EventHandler = Nothing)
        If TextBox IsNot Nothing Then Tag = TextBox
        Me.ItemOnClick = ItemOnClick
        MyBase.Show(Control.Parent.PointToScreen(New Point(Control.Left, Control.Bottom)))
    End Sub

    Public Sub New(Optional ByVal TargetTextBox As Windows.Forms.TextBox = Nothing)
        MyBase.New()
        Tag = TargetTextBox
    End Sub

    Public ReadOnly Property TextBox As Windows.Forms.TextBox
        Get
            Return TryCast(Tag, Windows.Forms.TextBox)
        End Get
    End Property

    Private Class ItemInsertingInTextBox
        Inherits Windows.Forms.ToolStripMenuItem

        Public Sub New(ByVal Text As String, ByVal InsertText As String)
            MyBase.New(New String(Text))
            Tag = New String(InsertText)
        End Sub

        Protected Overrides Sub OnClick(ByVal e As System.EventArgs)
            MyBase.OnClick(e)
            If DropDownItems Is Nothing OrElse DropDownItems.Count <= 0 Then
                Dim RecursiveGetOwner As Windows.Forms.ToolStrip = Owner
                Dim RecursiveGetOwnerItem As Windows.Forms.ToolStripItem = OwnerItem
                If RecursiveGetOwnerItem IsNot Nothing Then
                    While RecursiveGetOwnerItem.OwnerItem IsNot Nothing
                        RecursiveGetOwnerItem = RecursiveGetOwnerItem.OwnerItem
                    End While
                    RecursiveGetOwner = RecursiveGetOwnerItem.Owner
                End If
                Dim TextBox As Windows.Forms.TextBox = TryCast(RecursiveGetOwner.Tag, Windows.Forms.TextBox)
                If (Not Tag Is Nothing) And (Not TextBox Is Nothing) Then
                    TextBox.Paste(Tag.ToString)
                    Dim Strip As CustomContextMenu = TryCast(RecursiveGetOwner, CustomContextMenu)
                    If Strip IsNot Nothing AndAlso Strip.ItemOnClick IsNot Nothing Then
                        Strip.ItemOnClick(Me, New EventArgs)
                        Strip.ItemOnClick = Nothing
                    End If
                End If
            End If
        End Sub

    End Class

    Public Class InsertTextInRenamePolicyContextMenu
        Inherits CustomContextMenu

        Protected Overrides Sub OnOpening(ByVal e As System.ComponentModel.CancelEventArgs)
            Items.Clear()
            If Not TextBox Is Nothing Then Items.Add(New ItemInsertingInTextBox("%Name% (拡張子を除くファイル名)", "%Name%"))
            e.Cancel = False
            MyBase.OnOpening(e)
        End Sub

    End Class

    Public Class InsertTextInOpenAsContextMenu
        Inherits CustomContextMenu
        Protected Overrides Sub OnOpening(ByVal e As System.ComponentModel.CancelEventArgs)
            Items.Clear()
            If Not TextBox Is Nothing Then
                Dim GrpDQ As New Windows.Forms.ToolStripMenuItem("ダブルクオーテーション付与済みで置換されるワード")
                GrpDQ.DropDownItems.Add(New ItemInsertingInTextBox("%_RarPath_%", "%_RarPath_%"))
                GrpDQ.DropDownItems.Add(New ItemInsertingInTextBox("%_ArcPath_%", "%_ArcPath_%"))

                Items.Add(New ItemInsertingInTextBox("%% (%記号のエスケープ)", "%%"))
                Items.Add(New ItemInsertingInTextBox("%RarPath% (Rar.exeのパス)", "%RarPath%"))
                Items.Add(New ItemInsertingInTextBox("%ArcPath% (書庫ファイルのパス)", "%ArcPath%"))
                Items.Add(GrpDQ)
                e.Cancel = False
            End If
            MyBase.OnOpening(e)
        End Sub
    End Class

    Public Class InsertTextInScanCmdContextMenu
        Inherits CustomContextMenu
        Protected Overrides Sub OnOpening(ByVal e As System.ComponentModel.CancelEventArgs)
            Items.Clear()
            If Not TextBox Is Nothing Then
                Dim GrpDQ As New Windows.Forms.ToolStripMenuItem("ダブルクオーテーション付与済みで置換されるワード")
                GrpDQ.DropDownItems.Add(New ItemInsertingInTextBox("%_RarPath_%", "%_RarPath_%"))
                GrpDQ.DropDownItems.Add(New ItemInsertingInTextBox("%_ArcPath_%", "%_ArcPath_%"))

                Dim GrpProcCtrl As New Windows.Forms.ToolStripMenuItem("プロセスコントロール")
                GrpProcCtrl.DropDownItems.Add(New ItemInsertingInTextBox("%CreateWindow% (プロセス起動時にウィンドウ表示)", "%CreateWindow%"))
                GrpProcCtrl.DropDownItems.Add(New ItemInsertingInTextBox("%IgnoreStdOut% (プロセス実行時、標準出力を読み取らない)", "%IgnoreStdOut%"))

                Items.Add(New ItemInsertingInTextBox("%% (%記号のエスケープ)", "%%"))
                Items.Add(New ItemInsertingInTextBox("%RarPath% (Rar.exeのパス)", "%RarPath%"))
                Items.Add(New ItemInsertingInTextBox("%ArcPath% (書庫ファイルのパス)", "%ArcPath%"))
                Items.Add(GrpDQ)
                Items.Add(New Windows.Forms.ToolStripSeparator)
                Items.Add(GrpProcCtrl)
                e.Cancel = False
            End If
            MyBase.OnOpening(e)
        End Sub
    End Class

    Public Class InsertTextInCmdContextMenu
        Inherits CustomContextMenu
        Protected Overrides Sub OnOpening(ByVal e As System.ComponentModel.CancelEventArgs)
            Items.Clear()
            If Not TextBox Is Nothing Then
                Dim GrpDQ As New Windows.Forms.ToolStripMenuItem("ダブルクオーテーション付与済みで置換されるワード")
                GrpDQ.DropDownItems.Add(New ItemInsertingInTextBox("%_RarPath_%", "%_RarPath_%"))
                GrpDQ.DropDownItems.Add(New ItemInsertingInTextBox("%_ArcPath_%", "%_ArcPath_%"))
                GrpDQ.DropDownItems.Add(New ItemInsertingInTextBox("%_ExtractDir_%", "%_ExtractDir_%"))

                Dim GrpProcCtrl As New Windows.Forms.ToolStripMenuItem("プロセスコントロール")
                GrpProcCtrl.DropDownItems.Add(New ItemInsertingInTextBox("%CreateWindow% (プロセス起動時にウィンドウ表示)", "%CreateWindow%"))
                GrpProcCtrl.DropDownItems.Add(New ItemInsertingInTextBox("%IgnoreStdOut% (プロセス実行時、標準出力を読み取らない)", "%IgnoreStdOut%"))

                Items.Add(New ItemInsertingInTextBox("%% (%記号のエスケープ)", "%%"))
                Items.Add(New ItemInsertingInTextBox("%RarPath% (Rar.exeのパス)", "%RarPath%"))
                Items.Add(New ItemInsertingInTextBox("%ArcPath% (書庫ファイルのパス)", "%ArcPath%"))
                Items.Add(New ItemInsertingInTextBox("%ExtractDir% (書庫を展開したディレクトリパス)", "%ExtractDir%"))
                Items.Add(GrpDQ)
                Items.Add(New Windows.Forms.ToolStripSeparator)
                Items.Add(GrpProcCtrl)
                e.Cancel = False
            End If
            MyBase.OnOpening(e)
        End Sub
    End Class

    Public Class InsertTextInEntryCmdContextMenu
        Inherits CustomContextMenu
        Protected Overrides Sub OnOpening(ByVal e As System.ComponentModel.CancelEventArgs)
            Items.Clear()
            If Not TextBox Is Nothing Then
                Dim GrpDQ As New Windows.Forms.ToolStripMenuItem("ダブルクオーテーション付与済みで置換されるワード")
                GrpDQ.DropDownItems.Add(New ItemInsertingInTextBox("%_RarPath_%", "%_RarPath_%"))
                GrpDQ.DropDownItems.Add(New ItemInsertingInTextBox("%_ArcPath_%", "%_ArcPath_%"))
                GrpDQ.DropDownItems.Add(New ItemInsertingInTextBox("%_EntryPath_%", "%_EntryPath_%"))

                Dim GrpProcCtrl As New Windows.Forms.ToolStripMenuItem("プロセスコントロール")
                GrpProcCtrl.DropDownItems.Add(New ItemInsertingInTextBox("%CreateWindow% (プロセス起動時にウィンドウ表示)", "%CreateWindow%"))
                GrpProcCtrl.DropDownItems.Add(New ItemInsertingInTextBox("%StayPrompt% (実行後のプロンプト画面を残す)", "%StayPrompt%"))

                Items.Add(New ItemInsertingInTextBox("%% (%記号のエスケープ)", "%%"))
                Items.Add(New ItemInsertingInTextBox("%RarPath% (Rar.exeのパス)", "%RarPath%"))
                Items.Add(New ItemInsertingInTextBox("%ArcPath% (書庫ファイルのパス)", "%ArcPath%"))
                Items.Add(New ItemInsertingInTextBox("%EntryPath% (書庫エントリーのパス)", "%EntryPath%"))

                Items.Add(GrpDQ)
                Items.Add(New Windows.Forms.ToolStripSeparator)
                Items.Add(GrpProcCtrl)
                e.Cancel = False
            End If
            MyBase.OnOpening(e)
        End Sub
    End Class

End Class

Public Class CommandInfo

    ' public type ///////////////////////////////////////////////////////////////////////////////////////////////////

    Public Class ParseResult
        Public Result As Logic.CommandlineParser.ParseResult
        Public IsCreateWindow As Boolean = False
        Public IsIgnoreStdOut As Boolean = False
        Public IsStayPrompt As Boolean = False
        Public Overrides Function ToString() As String
            If Result Is Nothing Then Return Nothing
            Return Result.ToString()
        End Function
    End Class

    ' construct / destruct //////////////////////////////////////////////////////////////////////////////////////////
    Public Sub New(Optional ByVal AppBase As AppBase = Nothing)
        ParseTable = New ParseTableImpl
        Me.AppBase = AppBase
    End Sub

    ' public property ///////////////////////////////////////////////////////////////////////////////////////////////
    Public Property ArcPath As String
        Get
            Return ParseTable.Item("ArcPath")
        End Get
        Set(ByVal value As String)
            ParseTable.DoubleQuotedItem("ArcPath") = value
        End Set
    End Property

    Public Property ExtractDir As String
        Get
            Return ParseTable.Item("ExtractDir")
        End Get
        Set(ByVal value As String)
            ParseTable.DoubleQuotedItem("ExtractDir") = value
        End Set
    End Property

    Public Property EntryPath As String
        Get
            Return ParseTable.Item("EntryPath")
        End Get
        Set(ByVal value As String)
            ParseTable.DoubleQuotedItem("EntryPath") = value
        End Set
    End Property

    Public Property Name As String
        Get
            Return ParseTable.Item("Name")
        End Get
        Set(ByVal value As String)
            ParseTable.Item("Name") = value
        End Set
    End Property

    ' public methods /////////////////////////////////////////////////////////////////

    Public Function Parse(ByVal cmd As String) As ParseResult

        If cmd Is Nothing Then cmd = String.Empty

        Parse = New ParseResult

        If AppBase IsNot Nothing Then ParseTable.DoubleQuotedItem("RarPath") = AppBase.Archive.RarOptionConfig.RarPath

        Dim RetBuild As New System.Text.StringBuilder(cmd.Length)
        For Each Match As System.Text.RegularExpressions.Match In System.Text.RegularExpressions.Regex.Matches(cmd, "([^%]+)|%([^%]*?)%|%")

            If Not String.IsNullOrEmpty(Match.Groups(1).Value) Then
                If Not String.IsNullOrWhiteSpace(Match.Groups(1).Value) Then RetBuild.Append(Match.Groups(1).Value)

            ElseIf Match.Value = "%" Or Match.Value = "%%" Then
                RetBuild.Append("%")

            Else
                Dim key As String = Match.Groups(2).Value
                If String.Equals(key, "CreateWindow", StringComparison.OrdinalIgnoreCase) Then
                    Parse.IsCreateWindow = True

                ElseIf String.Equals(key, "IgnoreStdOut", StringComparison.OrdinalIgnoreCase) Then
                    Parse.IsIgnoreStdOut = True

                ElseIf String.Equals(key, "StayPrompt", StringComparison.OrdinalIgnoreCase) Then
                    Parse.IsStayPrompt = True

                ElseIf ParseTable.ContainsKey(key) AndAlso String.IsNullOrWhiteSpace(ParseTable(key)) = False Then
                    RetBuild.Append(ParseTable(key))

                ElseIf AppBase IsNot Nothing Then
                    AppBase.Echoing.Log.Echo(String.Format("Parse Error : %{0}% - String is Empty", key))
                    AppBase.Echoing.Log.Echo(String.Format("at This Command : {0}", cmd))
                End If

            End If

        Next

        Parse.Result = New Logic.CommandlineParser.ParseResult(RetBuild.ToString)

    End Function

    ' private implements //////////////////////////////////////////////////////

    Private AppBase As AppBase
    Private ParseTable As ParseTableImpl
    Private Class ParseTableImpl
        Inherits Collections.Generic.SortedDictionary(Of String, String)

        Public Sub New()
            MyBase.New(StringComparer.OrdinalIgnoreCase)
        End Sub

        Default Public Shadows Property Item(ByVal key As String) As String
            Get
                If ContainsKey(key) Then Return MyBase.Item(key)
                Return Nothing
            End Get
            Set(ByVal value As String)
                MyBase.Item(key) = value
            End Set
        End Property

        Public WriteOnly Property DoubleQuotedItem(ByVal key As String) As String
            Set(ByVal value As String)
                If String.IsNullOrWhiteSpace(value) Then
                    Remove(key)
                    Remove("_" & key & "_")
                Else
                    Item(key) = value
                    Item("_" & key & "_") = """" & value & """"
                End If
            End Set
        End Property

    End Class

End Class
