using System;
using System.Drawing;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Collections.Generic;
using FooEditEngine;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;
using FooEditor;
using FooEditEngine.Windows;
using FooEditor.Plugin;

namespace Outline
{
    public partial class OutlineForm : DockingForm
    {
        EditForm current;
        FooTextBox fooTextBox;
        List<int> OutlineLists = new List<int>();
        OutlineAnalyzer analyzer;
        bool realTimeAnalyze = true;
        string key;

        public OutlineForm()
        {
            InitializeComponent();
        }

        public OutlineForm(EditForm current, Dictionary<string, string[]> OutlineAnalyzePattern)
            : this()
        {
            this.analyzer = new OutlineAnalyzer(OutlineAnalyzePattern);
            this.currentForm = current;
            initComboBox(OutlineAnalyzePattern);
        }

        public EditForm currentForm
        {
            get { return this.current; }
            set {
                this.current = value;
                this.fooTextBox = value.fooTextBox1;
                this.current.fooTextBox1.Document.Update += new DocumentUpdateEventHandler(Document_Update);
                this.AnalyzeOutline(key);
            }
        }

        private void initComboBox(Dictionary<string, string[]> OutlineAnalyzePattern)
        {
            foreach (KeyValuePair<string, string[]> kv in OutlineAnalyzePattern)
            {
                ToolStripMenuItem newMenu = new ToolStripMenuItem();
                newMenu.Text = kv.Key;
                newMenu.Click += new EventHandler(newMenu_Click);
                this.analyzeMenuStrip.Items.Add(newMenu);
            }
        }

        void newMenu_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem menu = (ToolStripMenuItem)sender;
            this.key = menu.Text;

            this.AnalyzeOutline(key);
        }

        void Document_Update(object sender, DocumentUpdateEventArgs e)
        {
            if (this.current.isBusy || this.realTimeAnalyze == false)
                return;
            if (e.type == UpdateType.Replace)
                this.AnalyzeOutline(key);
        }

        private void AnalyzeOutline(string key)
        {
            bool result = this.analyzer.IsOutlineTextFormat(key);
            this.contextMenuStrip1.Enabled = result;
            this.treeView1.AllowDrop = result;

            this.analyzer.Analyze(this.treeView1, key, this.fooTextBox.LayoutLines);
        }

        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            Actions.JumpNode(this.treeView1.SelectedNode, this.fooTextBox);
        }

        private void 切り取りToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.realTimeAnalyze = false;
            Actions.CutNode(this.treeView1.SelectedNode, this.fooTextBox);
            this.AnalyzeOutline(this.key);
            this.realTimeAnalyze = true;
        }

        private void コピーToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.realTimeAnalyze = false;
            Actions.CopyNode(this.treeView1.SelectedNode, this.fooTextBox);
            this.AnalyzeOutline(this.key);
            this.realTimeAnalyze = true;
        }

        private void 上に貼り付けToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.treeView1.SelectedNode == null)
                return;
            this.realTimeAnalyze = false;
            Actions.PasteAs(this.treeView1.SelectedNode, PastTo.Upper, this.fooTextBox, this.key, this.analyzer, this.treeView1.SelectedNode.Level);
            this.AnalyzeOutline(this.key);
            this.realTimeAnalyze = true;
        }

        private void 下に貼り付けToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.treeView1.SelectedNode == null)
                return;
            this.realTimeAnalyze = false;
            Actions.PasteAs(this.treeView1.SelectedNode, PastTo.Lower, this.fooTextBox, this.key, this.analyzer, this.treeView1.SelectedNode.Level);
            this.AnalyzeOutline(this.key);
            this.realTimeAnalyze = true;
        }

        private void 子として貼り付けToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.treeView1.SelectedNode == null)
                return;
            this.realTimeAnalyze = false;
            string SelectedNodeText = this.treeView1.SelectedNode.Text;
            Actions.PasteAs(this.treeView1.SelectedNode, PastTo.Lower, this.fooTextBox, this.key, this.analyzer, this.treeView1.SelectedNode.Level + 1);
            this.AnalyzeOutline(this.key);
            Actions.ExpandTree(this.treeView1, SelectedNodeText);
            this.realTimeAnalyze = true;
        }

        private void treeView1_DragDrop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(typeof(TreeNode)))
            {
                TreeView tv = (TreeView)sender;
                TreeNode source = (TreeNode)e.Data.GetData(typeof(TreeNode));
                TreeNode target = tv.GetNodeAt(tv.PointToClient(new Point(e.X, e.Y)));
                //マウス下のNodeがドロップ先として適切か調べる
                if (target != null && target != source &&
                    !IsChildNode(source, target))
                {
                    this.realTimeAnalyze = false;
                    if (e.Effect == DragDropEffects.Move)
                    {
                        Actions.MoveNode(source,target, this.fooTextBox, this.key, this.analyzer);
                    }
                    else if (e.Effect == DragDropEffects.Copy)
                    {
                        Actions.CopyNode(source, target, this.fooTextBox, this.key, this.analyzer);
                    }
                    this.AnalyzeOutline(this.key);
                    Actions.ExpandTree(this.treeView1, target.Text);
                    this.realTimeAnalyze = true;
                }
                else
                    e.Effect = DragDropEffects.None;
            }
            else
                e.Effect = DragDropEffects.None;
        }

        private void treeView1_DragOver(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(typeof(TreeNode)))
            {
                if ((e.KeyState & 8) == 8 &&
                    (e.AllowedEffect & DragDropEffects.Copy) ==
                    DragDropEffects.Copy)
                    //Ctrlキーが押されていればCopy
                    //"8"はCtrlキーを表す
                    e.Effect = DragDropEffects.Copy;
                else if ((e.AllowedEffect & DragDropEffects.Move) ==
                    DragDropEffects.Move)
                    //何も押されていなければMove
                    e.Effect = DragDropEffects.Move;
                else
                    e.Effect = DragDropEffects.None;
            }
            else
                e.Effect = DragDropEffects.None;

            if (e.Effect != DragDropEffects.None)
            {
                TreeView tv = (TreeView)sender;
                TreeNode target = tv.GetNodeAt(tv.PointToClient(new Point(e.X, e.Y)));
                TreeNode source = (TreeNode)e.Data.GetData(typeof(TreeNode));
                //マウス下のNodeがドロップ先として適切か調べる
                if (target != null && target != source &&
                        !IsChildNode(source, target))
                {
                    //Nodeを選択する
                    if (target.IsSelected == false)
                        tv.SelectedNode = target;
                }
                else
                    e.Effect = DragDropEffects.None;
            }
        }

        private static bool IsChildNode(TreeNode parent, TreeNode child)
        {
            if (child.Parent == parent)
                return true;
            else if (child.Parent != null)
                return IsChildNode(parent, child.Parent);
            else
                return false;
        }
        
        private void treeView1_ItemDrag(object sender, ItemDragEventArgs e)
        {
            TreeView tv = (TreeView)sender;
            tv.SelectedNode = (TreeNode)e.Item;
            tv.Focus();
            DragDropEffects dde = tv.DoDragDrop(e.Item, DragDropEffects.All);
            if ((dde & DragDropEffects.Move) == DragDropEffects.Move)
                tv.Nodes.Remove((TreeNode)e.Item);
        }

        private void レベル上げるToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.treeView1.SelectedNode == null)
                return;
            this.realTimeAnalyze = false;
            Actions.ChangeNodeLevel(this.treeView1.SelectedNode, this.fooTextBox, this.key, this.analyzer, this.treeView1.SelectedNode.Level + 1);
            this.realTimeAnalyze = true;
        }

        private void レベル下げるToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (this.treeView1.SelectedNode == null)
                return;
            this.realTimeAnalyze = false;
            Actions.ChangeNodeLevel(this.treeView1.SelectedNode, this.fooTextBox, this.key, this.analyzer, this.treeView1.SelectedNode.Level - 1);
            this.realTimeAnalyze = true;
        }

    }
}
