' *
' * 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 Class SettingPanel

    Public Sub New()

        InitializeComponent()
        Splitter.Panel1MinSize = ListNew.Width + ListDel.Width + ListUp.Width + ListDown.Width

        EntryTaskNode = TreeView.Nodes("EntryTaskNode")
        ArchiveTaskNode = TreeView.Nodes("ArchiveTaskNode")
        ConfigRootNode = TreeView.Nodes("ConfigRoot")
        ConfigImagingNode = ConfigRootNode.Nodes("ConfigImaging")
        ListControlNode = {EntryTaskNode, ArchiveTaskNode}

        ConfigMessage = New Collections.Generic.Dictionary(Of Windows.Forms.TreeNode, String)
        ConfigMessage.Add(EntryTaskNode, "エントリータスクは書庫内エントリーを操作します。エントリータスクはエントリーリストのコンテキストから呼び出して使用できます。")

        ConfigSelect = New Collections.Generic.Dictionary(Of Windows.Forms.TreeNode, IAppBase)
        ConfigSelect.Add(ConfigRootNode, ConfigRootPanel1)
        ConfigSelect.Add(ConfigImagingNode, ConfigImagingPanel1)
        ConfigSelect.Add(ArchiveTaskNode, ConfigArchiveTaskPanel)

        SettingPanels = New SettingPanelCollection(Me)
        TreeViewSelChangedHandler.Add(AddressOf TreeView_AfterSelectImpl)

    End Sub

    ' public properties ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    Private m_SizeEventEnable As Boolean = False
    Public Property SizeEventEnable As Boolean
        Get
            SizeEventEnable = m_SizeEventEnable
        End Get
        Set(ByVal value As Boolean)
            If m_SizeEventEnable <> value Then
                m_SizeEventEnable = value
                TreeView_AfterSelectImpl(Nothing, Nothing)
                If value Then
                    If AppBase IsNot Nothing AndAlso (ParentForm.WindowState = FormWindowState.Normal Or ParentForm.WindowState = FormWindowState.Maximized) Then
                        If 0 < AppBase.Config.WindowSize(Me.ParentForm.WindowState).SettingPanelSplitDistance Then Splitter.SplitterDistance = AppBase.Config.WindowSize(Me.ParentForm.WindowState).SettingPanelSplitDistance
                    End If
                    SplitterMovedHandler.Add(AddressOf Splitter_SplitterMovedImpl)
                Else
                    SplitterMovedHandler.Clear()
                End If
            End If
        End Set
    End Property

    Private m_AppBase As AppBase = Nothing
    Public Property AppBase As AppBase
        Get
            Return m_AppBase
        End Get
        Set(ByVal value As AppBase)

            TreeView.SelectedNode = Nothing
            TreeView_AfterSelectImpl(Nothing, Nothing)

            m_SizeEventEnable = False

            If IsDisposed = False And Disposing = False Then
                EntryTaskNode.Nodes.Clear()
                ArchiveTaskNode.Nodes.Clear()
            End If

            m_AppBase = value

            PresetArchiveTaskPanelControl1.AppBase = value
            PresetEntryTaskPanelControl1.AppBase = value

            If AppBase Is Nothing Then Return

            If 0 < AppBase.EntryTaskPresets.Count Then
                For idx As Integer = 0 To AppBase.EntryTaskPresets.Count - 1
                    Dim item As New TreeNode(AppBase.EntryTaskPresets(idx).Name)
                    item.Name = item.Text
                    EntryTaskNode.Nodes.Add(item)
                Next
            End If

            If 0 < AppBase.ArchiveTaskPresets.Count Then
                For idx As Integer = 0 To AppBase.ArchiveTaskPresets.Count - 1
                    Dim item As New TreeNode(AppBase.ArchiveTaskPresets(idx).Name)
                    item.Name = item.Text
                    ArchiveTaskNode.Nodes.Add(item)
                Next
            End If

            TreeView.ExpandAll()

        End Set
    End Property

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

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

    Private Class SettingPanelCollection

        Private ReadOnly GroupBox As Control
        Private ReadOnly ary As Collections.Generic.List(Of Windows.Forms.Control)
        Private ReadOnly SubListCtrlPanel As Windows.Forms.Control

        Public Sub New(ByVal SettingPanel As SettingPanel)

            Dim items() As Control = { _
                SettingPanel.ConfigRootPanel1, _
                SettingPanel.ConfigImagingPanel1, _
                SettingPanel.ConfigArchiveTaskPanel, _
                SettingPanel.ConfigMessagePanel1, _
                SettingPanel.PresetArchiveTaskPanelControl1, _
                SettingPanel.PresetEntryTaskPanelControl1
            }
            ary = New Collections.Generic.List(Of Windows.Forms.Control)(items)

            For Each Panel As Windows.Forms.Control In items
                Panel.Visible = True
            Next
            For Each Panel As Windows.Forms.Control In items
                Panel.Visible = False
            Next
            For Each Panel As Windows.Forms.Control In items
                Panel.Dock = Windows.Forms.DockStyle.Fill
            Next

            GroupBox = SettingPanel.SettingBasePanel
            SubListCtrlPanel = SettingPanel.SubListControlPanel

        End Sub

        Public Sub Switch(Optional ByVal EnablePanel As Windows.Forms.Control = Nothing, Optional ByVal SubListControlVisible As Boolean = False)

            If EnablePanel IsNot Nothing AndAlso EnablePanel.Visible = True Then
                If SubListCtrlPanel IsNot Nothing AndAlso SubListCtrlPanel.Visible <> SubListControlVisible Then SubListCtrlPanel.Visible = SubListControlVisible
                Return
            End If

            If EnablePanel IsNot Nothing Then EnablePanel.Parent.SuspendLayout()

            For Each Panel As Windows.Forms.Control In ary
                If Panel IsNot EnablePanel AndAlso Panel.Visible = True Then Panel.Visible = False
            Next

            If SubListCtrlPanel IsNot Nothing AndAlso SubListCtrlPanel.Visible <> SubListControlVisible Then SubListCtrlPanel.Visible = SubListControlVisible
            If EnablePanel Is Nothing Then
                GroupBox.Text = "操作が選択されていません。"
            Else
                If EnablePanel.Visible = False Then EnablePanel.Visible = True
                EnablePanel.Parent.ResumeLayout()
            End If

        End Sub

    End Class

    Private ReadOnly SettingPanels As SettingPanelCollection
    Private ReadOnly ListControlNode As TreeNode()
    Private ReadOnly EntryTaskNode As TreeNode
    Private ReadOnly ArchiveTaskNode As TreeNode
    Private ReadOnly ConfigRootNode As TreeNode
    Private ReadOnly ConfigImagingNode As TreeNode
    Private ReadOnly ConfigSelect As Collections.Generic.Dictionary(Of Windows.Forms.TreeNode, IAppBase)
    Private ReadOnly ConfigMessage As Collections.Generic.Dictionary(Of Windows.Forms.TreeNode, String)
    Private ReadOnly SplitterMovedHandler As New Logic.UniqueEvents(Of SplitterEventArgs)
    Private ReadOnly TreeViewSelChangedHandler As New Logic.UniqueEvents(Of TreeViewEventArgs)
    Private CurrentViewPanel As Control = Nothing

    Private Sub Splitter_SplitterMovedImpl(ByVal sender As System.Object, ByVal e As System.Windows.Forms.SplitterEventArgs)
        If (m_SizeEventEnable And Not AppBase Is Nothing) AndAlso (Me.ParentForm.WindowState = FormWindowState.Normal Or Me.ParentForm.WindowState = FormWindowState.Maximized) Then
            AppBase.Config.WindowSize(Me.ParentForm.WindowState).SettingPanelSplitDistance = Splitter.SplitterDistance
        End If
    End Sub

    Private Sub Splitter_SplitterMoved(ByVal sender As System.Object, ByVal e As System.Windows.Forms.SplitterEventArgs) Handles Splitter.SplitterMoved
        SplitterMovedHandler.Invoke(sender, e)
    End Sub

    Private Sub PresetPanel_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
        AppBase = Nothing
        SplitterMovedHandler.Clear()
        TreeViewSelChangedHandler.Clear()
    End Sub

    Private Sub TreeView_AfterSelectImpl(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewEventArgs)

        CurrentViewPanel = Nothing

        ListNew.Enabled = False
        ListDel.Enabled = False
        ListUp.Enabled = False
        ListDown.Enabled = False
        TreeView.LabelEdit = False

        Dim isSubListCtrl As Boolean = False
        If TreeView.SelectedNode Is Nothing OrElse TreeView.SelectedNode.IsSelected = False Then
            ' do nothing
        Else
            ' set list controls' enable /////////////////////////////////////////////////////////////////////
            For Each node As TreeNode In ListControlNode
                If TreeView.SelectedNode Is node Then
                    isSubListCtrl = True
                    ListNew.Enabled = True
                    Exit For
                ElseIf TreeView.SelectedNode.Parent Is node Then
                    ListNew.Enabled = True
                    ListDel.Enabled = True
                    ListUp.Enabled = True
                    ListDown.Enabled = True
                    TreeView.LabelEdit = True
                    Exit For
                End If
            Next

            '  set CurrentViewPanel //////////////////////////////////////////////////////////////////////
            If ConfigMessage.ContainsKey(TreeView.SelectedNode) Then
                SettingBasePanel.Text = TreeView.SelectedNode.Text
                ConfigMessagePanel1.Message = ConfigMessage(TreeView.SelectedNode)
                CurrentViewPanel = ConfigMessagePanel1

            ElseIf ConfigSelect.ContainsKey(TreeView.SelectedNode) Then
                SettingBasePanel.Text = TreeView.SelectedNode.Text
                ConfigSelect(TreeView.SelectedNode).AppBase = AppBase ' Apply AppBase Data
                CurrentViewPanel = ConfigSelect(TreeView.SelectedNode)

            ElseIf TreeView.SelectedNode.Parent Is ArchiveTaskNode Then
                Dim Preset As AppBase.ArchiveTaskPreset = AppBase.ArchiveTaskPresets(TreeView.SelectedNode.Name)
                If Preset IsNot Nothing Then
                    SettingBasePanel.Text = Preset.Name
                    PresetArchiveTaskPanelControl1.CurrentPreset = Preset
                    CurrentViewPanel = PresetArchiveTaskPanelControl1
                Else
#If DEBUG Then
                    Throw New ApplicationException
#End If
                End If

            ElseIf TreeView.SelectedNode.Parent Is EntryTaskNode Then
                Dim Preset As AppBase.EntryTaskPreset = AppBase.EntryTaskPresets(TreeView.SelectedNode.Name)
                If Preset IsNot Nothing Then
                    SettingBasePanel.Text = Preset.Name
                    PresetEntryTaskPanelControl1.CurrentPreset = Preset
                    CurrentViewPanel = PresetEntryTaskPanelControl1
                Else
#If DEBUG Then
                    Throw New ApplicationException
#End If
                End If
            End If

        End If

        SettingPanels.Switch(CurrentViewPanel, isSubListCtrl)

        If CurrentViewPanel Is PresetArchiveTaskPanelControl1 Then PresetArchiveTaskPanelControl1.SizeEventEnable = True

    End Sub

    Private Sub TreeView_AfterLabelEdit(ByVal sender As Object, ByVal e As System.Windows.Forms.NodeLabelEditEventArgs) Handles TreeView.AfterLabelEdit

        If e.Label Is Nothing Then Return

        e.CancelEdit = True

        For Each family As TreeNode In e.Node.Parent.Nodes
            If family IsNot e.Node And family.Name = e.Label Then
                MsgBox("Please Unique Name")
                Return
            End If
        Next

        Dim Preset As Logic.INamed = Nothing
        If e.Node.Parent Is ArchiveTaskNode Then
            Preset = AppBase.ArchiveTaskPresets(e.Node.Name)
        ElseIf e.Node.Parent Is EntryTaskNode Then
            Preset = AppBase.EntryTaskPresets(e.Node.Name)
        End If

        If Preset Is Nothing Then Return

        Preset.Name = e.Label
        e.Node.Name = e.Label
        e.CancelEdit = False

    End Sub

    Private Sub TreeView_AfterSelect(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles TreeView.AfterSelect
        TreeViewSelChangedHandler.Invoke(sender, e)
    End Sub

    Private Sub TreeView_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles TreeView.KeyUp
        Select Case e.KeyData
            Case Keys.F2
                If (TreeView.SelectedNode IsNot Nothing AndAlso TreeView.SelectedNode.IsSelected) And TreeView.LabelEdit Then TreeView.SelectedNode.BeginEdit()
        End Select
    End Sub

    Private Sub PresetNew_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListNew.Click, SubListNew.Click

        If TreeView.SelectedNode.Parent Is ArchiveTaskNode Or TreeView.SelectedNode Is ArchiveTaskNode Then

            Dim ct As Long = 1
            Do While Not (AppBase.ArchiveTaskPresets("NewPreset" & CStr(ct)) Is Nothing)
                ct = ct + 1
            Loop

            Dim NewTitle As String = InputBox("新しいプリセットの名前を設定して下さい。", "プリセットの新規追加", "NewPreset" & CStr(ct))
            If String.IsNullOrEmpty(NewTitle) Then

                ' cancel, do nothing

            ElseIf String.IsNullOrWhiteSpace(NewTitle) Then

                MsgBox("空白以外の名前を入力してください。")

            ElseIf Not (AppBase.ArchiveTaskPresets(NewTitle) Is Nothing) Then

                MsgBox(NewTitle & "は既に存在します。新しい名前を設定して下さい。")

            ElseIf AppBase.ArchiveTaskPresets.Add(New AppBase.ArchiveTaskPreset(NewTitle)) Then

                Dim item As New TreeNode(NewTitle)
                item.Name = NewTitle
                TreeViewSelChangedHandler.Clear()
                ArchiveTaskNode.Nodes.Add(item)
                TreeViewSelChangedHandler.Add(AddressOf TreeView_AfterSelectImpl)
                TreeView.SelectedNode = item

            End If

        ElseIf TreeView.SelectedNode.Parent Is EntryTaskNode Or TreeView.SelectedNode Is EntryTaskNode Then

            Dim ct As Long = 1
            Do While Not (AppBase.EntryTaskPresets("NewPreset" & CStr(ct)) Is Nothing)
                ct = ct + 1
            Loop

            Dim NewTitle As String = InputBox("新しいプリセットの名前を設定して下さい。", "プリセットの新規追加", "NewPreset" & CStr(ct))
            If String.IsNullOrWhiteSpace(NewTitle) Then

                MsgBox("空白以外の名前を入力してください。")

            ElseIf Not (AppBase.EntryTaskPresets(NewTitle) Is Nothing) Then

                MsgBox(NewTitle & "は既に存在します。新しい名前を設定して下さい。")

            ElseIf AppBase.EntryTaskPresets.Add(New AppBase.EntryTaskPreset(NewTitle)) Then

                Dim item As New TreeNode(NewTitle)
                item.Name = NewTitle
                TreeViewSelChangedHandler.Clear()
                EntryTaskNode.Nodes.Add(item)
                TreeViewSelChangedHandler.Add(AddressOf TreeView_AfterSelectImpl)
                TreeView.SelectedNode = item

            End If

        End If

    End Sub

    Private Sub PresetDel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListDel.Click

        If TreeView.SelectedNode Is Nothing Then Return

        If TreeView.SelectedNode.Parent Is ArchiveTaskNode Then

            Dim Preset As AppBase.ArchiveTaskPreset = AppBase.ArchiveTaskPresets(TreeView.SelectedNode.Name)
            If Preset IsNot Nothing Then
                If MsgBox("既存のプリセット " & Preset.Name & " を削除しますか？", vbOKCancel, "プリセットの削除") <> vbOK Then Exit Sub
                ArchiveTaskNode.Nodes.Remove(TreeView.SelectedNode)
                AppBase.ArchiveTaskPresets.Remove(Preset.Name)
            Else
#If DEBUG Then
                Throw New ApplicationException
#End If
            End If

        ElseIf TreeView.SelectedNode.Parent Is EntryTaskNode Then

            Dim Preset As AppBase.EntryTaskPreset = AppBase.EntryTaskPresets(TreeView.SelectedNode.Name)
            If Preset IsNot Nothing Then
                If MsgBox("既存のプリセット " & Preset.Name & " を削除しますか？", vbOKCancel, "プリセットの削除") <> vbOK Then Exit Sub
                EntryTaskNode.Nodes.Remove(TreeView.SelectedNode)
                AppBase.EntryTaskPresets.Remove(Preset.Name)
            Else
#If DEBUG Then
                Throw New ApplicationException
#End If
            End If

        End If

    End Sub

    Private Sub PresetUp_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListUp.Click

        If TreeView.SelectedNode Is Nothing Then Return

        Dim item As TreeNode = TreeView.SelectedNode
        Dim idx As Integer = item.Index - 1

        If TreeView.SelectedNode.Parent Is ArchiveTaskNode Then

            If idx < 0 Or ArchiveTaskNode.Nodes.Count - 1 < idx Then Return

            Dim Preset As AppBase.ArchiveTaskPreset = AppBase.ArchiveTaskPresets(item.Text)
            If Preset Is Nothing Then Return
            AppBase.ArchiveTaskPresets.Remove(Preset.Name)
            AppBase.ArchiveTaskPresets.Insert(Preset, idx)

            TreeViewSelChangedHandler.Clear()
            ArchiveTaskNode.Nodes.Remove(item)
            ArchiveTaskNode.Nodes.Insert(idx, item)
            TreeView.SelectedNode = item
            TreeViewSelChangedHandler.Add(AddressOf TreeView_AfterSelectImpl)

        ElseIf TreeView.SelectedNode.Parent Is EntryTaskNode Then

            If idx < 0 Or EntryTaskNode.Nodes.Count - 1 < idx Then Return

            Dim Preset As AppBase.EntryTaskPreset = AppBase.EntryTaskPresets(item.Text)
            If Preset Is Nothing Then Return
            AppBase.EntryTaskPresets.Remove(Preset.Name)
            AppBase.EntryTaskPresets.Insert(Preset, idx)

            TreeViewSelChangedHandler.Clear()
            EntryTaskNode.Nodes.Remove(item)
            EntryTaskNode.Nodes.Insert(idx, item)
            TreeView.SelectedNode = item
            TreeViewSelChangedHandler.Add(AddressOf TreeView_AfterSelectImpl)

        End If

    End Sub

    Private Sub PresetDown_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListDown.Click

        If TreeView.SelectedNode Is Nothing Then Return

        Dim item As TreeNode = TreeView.SelectedNode
        Dim idx As Integer = item.Index + 1

        If TreeView.SelectedNode.Parent Is ArchiveTaskNode Then

            If idx < 0 Or ArchiveTaskNode.Nodes.Count - 1 < idx Then Return

            Dim Preset As AppBase.ArchiveTaskPreset = AppBase.ArchiveTaskPresets(item.Text)
            If Preset Is Nothing Then Return
            AppBase.ArchiveTaskPresets.Remove(Preset.Name)
            AppBase.ArchiveTaskPresets.Insert(Preset, idx)

            TreeViewSelChangedHandler.Clear()
            ArchiveTaskNode.Nodes.Remove(item)
            ArchiveTaskNode.Nodes.Insert(idx, item)
            TreeView.SelectedNode = item
            TreeViewSelChangedHandler.Add(AddressOf TreeView_AfterSelectImpl)

        ElseIf TreeView.SelectedNode.Parent Is EntryTaskNode Then

            If idx < 0 Or EntryTaskNode.Nodes.Count - 1 < idx Then Return

            Dim Preset As AppBase.EntryTaskPreset = AppBase.EntryTaskPresets(item.Text)
            If Preset Is Nothing Then Return
            AppBase.EntryTaskPresets.Remove(Preset.Name)
            AppBase.EntryTaskPresets.Insert(Preset, idx)

            TreeViewSelChangedHandler.Clear()
            EntryTaskNode.Nodes.Remove(item)
            EntryTaskNode.Nodes.Insert(idx, item)
            TreeView.SelectedNode = item
            TreeViewSelChangedHandler.Add(AddressOf TreeView_AfterSelectImpl)

        End If

    End Sub

End Class
