using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Diagnostics;
using FooEditEngine;
using FooEditEngine.Windows;
using FooEditor.Properties;
using FooEditor.Plugin;
using WeifenLuo.WinFormsUI.Docking;
using EncodeDetect;

namespace FooEditor
{
    public partial class MainForm : Form
    {
        const int TimerInterval = 100;
        private FindReplaceDialog frd;
        private IPCServer Server;
        private Config cfg;
        private Editor editor;
        private FooPrintText Print = new FooPrintText();
        private PluginManager<IPlugin> plugins;

        public MainForm()
        {
            InitializeComponent();

            this.cfg = Config.GetInstance();
            this.cfg.RecentFile.RecentFileUpdateEventHandler += new RecentFileUpdateEvent(RecentFile_RecentFileAddEventHandler);
            this.cfg.Load();

            this.plugins = new PluginManager<IPlugin>(this.cfg.DontLoadPlugins);

            this.Text = Resources.AppName;
        }

        public static string PipeServerName
        {
            get
            {
                return Resources.IPCServerName+ "." + Process.GetCurrentProcess().SessionId;
            }
        }

        private void 開くToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EditForm active = this.dockPanel1.ActiveDocument as EditForm;
            this.editor.LoadFromDialog(active);
        }

        private void 閉じるCToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EditForm active = this.dockPanel1.ActiveDocument as EditForm;
            active.Close();
        }

        private void 名前を付けて保存ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EditForm active = this.dockPanel1.ActiveDocument as EditForm;
            if (active == null)
                return;
            this.editor.SaveAs(active);
        }

        private void 上書きToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EditForm active = this.dockPanel1.ActiveDocument as EditForm;
            if (active == null)
                return;
            if (active.filepath == null)
                名前を付けて保存ToolStripMenuItem_Click(sender, e);
            else
                this.editor.SaveFileAsync(active, active.filepath);
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            this.Location = new Point(0, 0);
            this.Size = new Size(this.cfg.Width, this.cfg.Height);

            this.editor = new Editor(this.dockPanel1);
            this.editor.RootMenuStrip = this.menuStrip1;
            this.editor.ContextMenuStrip = this.contextMenuStrip1;
            this.editor.CreateingEditFormEvent += new CreateEditFormEventHandler(editor_CrateEditFromEvent);

            foreach (IPlugin plugin in this.plugins)
                plugin.Initalize(this.editor);

            this.dockPanel1.Extender.AutoHideStripFactory = null;
            this.dockPanel1.Extender.DockPaneCaptionFactory = null;
            this.dockPanel1.Extender.DockPaneStripFactory = null;

            this.RecoveryEvent();
            this.editor.CreateNew();
        }

        private void MainForm_Shown(object sender, EventArgs e)
        {
            if (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 1)
            {
                TaskBar taskbar = TaskBar.GetInstance();
                taskbar.InitJumpList();
            }

            this.ReadStdin();

            Server = new IPCServer(MainForm.PipeServerName);
            Server.Recive += new ServerReciveEventHandler(Server_Recive);

            Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
        }

        void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
        {
            if (e.Exception is UserOperationException)
            {
                MessageBox.Show(this,e.Exception.Message,Resources.ErrorDialogTitle);
                return;
            }
            ExceptionDialog ExceptionDialog = new ExceptionDialog(e.Exception);
            if (ExceptionDialog.ShowDialog() == System.Windows.Forms.DialogResult.Ignore)
                return;
            SaveCurrentStates();
            Environment.Exit(0);
        }

        private void コピーCToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EditForm active = this.dockPanel1.ActiveDocument as EditForm;
            if (active == null)
                return;
            active.fooTextBox1.Copy();
        }

        private void 切り取りXToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EditForm active = this.dockPanel1.ActiveDocument as EditForm;
            if (active == null)
                return;
            active.fooTextBox1.Cut();
            this.Refresh();
        }

        private void 貼り付けPToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EditForm active = this.dockPanel1.ActiveDocument as EditForm;
            if (active == null)
                return;
            active.fooTextBox1.Paste();
            this.Refresh();
        }

        private void 元に戻すUToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EditForm active = this.dockPanel1.ActiveDocument as EditForm;
            if (active == null)
                return;
            active.fooTextBox1.Document.UndoManager.undo();
            this.Refresh();
        }

        private void 検索FToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EditForm active = this.dockPanel1.ActiveDocument as EditForm;
            if (active == null)
                return;
            if (frd == null || frd.IsDisposed == true)
                frd = new FindReplaceDialog(active.fooTextBox1);
            frd.Show(this.dockPanel1,DockState.DockLeft);
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            this.cfg.Height = this.Height;
            this.cfg.Width = this.Width;
            this.cfg.Save();
            if (this.Server != null)
                this.Server.Dispose();
            foreach (IPlugin plugin in this.plugins)
                plugin.ClosedApp();
        }

        private void 終了QToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void 置き換えHToolStripMenuItem_Click(object sender, EventArgs e)
        {
            検索FToolStripMenuItem_Click(sender, e);
        }

        private void EditForm_DragDrop(object sender, DragEventArgs e)
        {
            string[] dlagFilePathArray = (string[])e.Data.GetData(DataFormats.FileDrop, false);

            for (int i = 0; i < dlagFilePathArray.Length; i++)
            {
                EditForm newForm = this.editor.CreateNew();
                newForm.LoadFileAsync(dlagFilePathArray[i],null);
            }
        }

        private void EditForm_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
                e.Effect = DragDropEffects.All;
            else
                e.Effect = DragDropEffects.None;
        }

        private void すべてを選択AToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EditForm active = this.dockPanel1.ActiveDocument as EditForm;
            if (active == null)
                return;
            active.fooTextBox1.SelectAll();
            active.Refresh();
        }

        private void RecentFile_menuitem_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem item = (ToolStripMenuItem)sender;
            
            EditForm form = this.editor.EditForm;
            
            if (form == null)
                form = this.editor.CreateNew();

            form.LoadFileAsync((string)item.Tag,null);
        }

        private void LineFeedSelect_menuitem_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem item = (ToolStripMenuItem)sender;
            EditForm active = this.dockPanel1.ActiveContent as EditForm;
            if (active == null)
                return;
            active.linefeed = (LineFeedType)Int32.Parse((string)item.Tag);
        }

        private void CodeSelect_menuitem_Click(object sender, EventArgs e)
        {
            EditForm active = this.dockPanel1.ActiveDocument as EditForm;
            if (active == null)
                return;
            ToolStripMenuItem item = (ToolStripMenuItem)sender;
            Encoding enc = Encoding.GetEncoding((string)item.Tag);
            if (active.filepath != null && MessageBox.Show(Resources.ReloadConfirm, "", MessageBoxButtons.YesNo) == DialogResult.Yes)
                active.LoadFileAsync(active.filepath, enc);
            else
                active.enc = enc;
        }

        private void DocumentModeMenuClick(object sender, EventArgs e)
        {
            EditForm active = this.dockPanel1.ActiveDocument as EditForm;
            if (active == null)
                return;
            ToolStripMenuItem item = (ToolStripMenuItem)sender;
            if (item.Text == Resources.DocumentModeNone)
                active.DocumentType = null;
            else
                active.DocumentType = item.Text;
        }

        void Server_Recive(object sender, ServerReciveEventArgs e)
        {
            string data = e.StreamReader.ReadLine();

            PipeCommandListener listener = new PipeCommandListener(this, this.editor);

            listener.Execute(data);
        }

        private void やり直すToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EditForm active = this.dockPanel1.ActiveDocument as EditForm;
            if (active == null)
                return;
            active.fooTextBox1.Document.UndoManager.redo();
            this.Refresh();
        }

        private void 新規作成ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.editor.CreateNew();
        }

        private void 行ジャンプToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EditForm active = this.dockPanel1.ActiveDocument as EditForm;
            if (active == null)
                return;
            LineJump frm = new LineJump(active.fooTextBox1);
            frm.ShowDialog();
        }

        private void 印刷プレビューToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EditForm active = this.dockPanel1.ActiveDocument as EditForm;
            if (active == null)
                return;
            PrintHFParser Parser = new PrintHFParser(active);
            Print.Document = active.fooTextBox1.Document;
            Print.isWordRap = cfg.WordRap;
            Print.Font = active.fooTextBox1.Font;
            Print.DrawLineNumber = active.fooTextBox1.DrawLineNumber;
            Print.Header = Resources.DefalutHeader;
            Print.Footer = Resources.DefaultFooter;
            Print.ParseHF = Parser.Parse;
            PrintPreviewDialog ppd = new PrintPreviewDialog();
            ppd.Document = Print.PrintDocument;
            ppd.Show();
        }

        private void ページ設定ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EditForm active = this.dockPanel1.ActiveDocument as EditForm;
            if (active == null)
                return;
            PageSetupDialog pagesetup = new PageSetupDialog();
            pagesetup.Document = Print.PrintDocument;
            pagesetup.EnableMetric = true;
            pagesetup.ShowDialog();
        }

        private void 印刷ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EditForm active = this.dockPanel1.ActiveDocument as EditForm;
            if (active == null)
                return;
            PrintHFParser Parser = new PrintHFParser(active);
            Print.Document = active.fooTextBox1.Document;
            Print.Font = active.fooTextBox1.Font;
            Print.DrawLineNumber = active.fooTextBox1.DrawLineNumber;
            Print.isWordRap = cfg.WordRap;
            Print.Header = Resources.DefalutHeader;
            Print.Footer = Resources.DefaultFooter;
            Print.ParseHF = Parser.Parse;
            PrintDialog pd = new PrintDialog();
            pd.AllowSomePages = true;
            pd.UseEXDialog = true;
            pd.Document = Print.PrintDocument;
            if (pd.ShowDialog() == DialogResult.Cancel)
                return;
            try
            {
                Print.PrintDocument.Print();
            }
            catch (Exception ex)
            {
                throw new UserOperationException(ex.Message);
            }
            finally
            {
                pd.Dispose();
            }
        }

        private void 目次ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Help.ShowHelp(this, Resources.HelpFileName);
        }

        private void バージョン情報ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string str = string.Format("{0} version{1}\n{2}", Application.ProductName, Application.ProductVersion,Application.CompanyName);
            MessageBox.Show(str, "FooEditorについて");
        }

        void EditForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            EditForm active = sender as EditForm;
            if (active == null)
                return;

            if (active.isDirty)
            {
                DialogResult result = MessageBox.Show(Resources.CloseConfirm, active.Text, MessageBoxButtons.YesNoCancel);
                if (result == DialogResult.Yes)
                {
                    if (active.filepath == null)
                        this.editor.SaveAs(active);
                    else
                        this.editor.SaveFileAsync(active, active.filepath);
                }
                else if (result == DialogResult.Cancel)
                {
                    e.Cancel = true;
                    return;
                }
            }
        }

        private void ToggleRectSelectionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EditForm active = this.dockPanel1.ActiveDocument as EditForm;
            if (active == null)
                return;
            active.fooTextBox1.RectSelection = ToggleRectSelectionToolStripMenuItem.Checked;
        }

        private void dockPanel1_ActiveContentChanged(object sender, EventArgs e)
        {
            EditForm active = this.dockPanel1.ActiveContent as EditForm;
            
            if (this.editor != null)
            {
                this.editor.EditForm = active;
                this.editor.TextBox = active != null ? active.fooTextBox1 : null;
            }

            if (active == null)
                return;

            DocumentModeToolStripMenuItem.DropDownItems.SwitchChckedItem(active.DocumentType == null ? Resources.DocumentModeNone : active.DocumentType);
            EncodeToolStripMenuItem.DropDownItems.SwitchChckedItem(active.enc.EncodingName);
            EditForm_EncodeChangeEventHandler(active, null);
            EditForm_DocumentChangeTypeEventHandler(active, null);
            EditForm_LinefeedTypeChangeEventHandler(active, null);
            fooTextBox1_InsetModeChange(active.fooTextBox1, null);

            if (frd != null && frd.IsDisposed == false)
                frd.fooTextBox = active.fooTextBox1;
        }

        private void grepGToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!File.Exists(this.cfg.GrepPath))
                return;
            ProcessStartInfo info = new ProcessStartInfo();
            info.FileName = this.cfg.GrepPath;
            info.Verb = "open";
            info.UseShellExecute = true;
            Process process = Process.Start(info);
        }

        void dockPanel1_ContentRemoved(object sender, DockContentEventArgs e)
        {
            if (this.dockPanel1.DocumentsCount > 0)
                return;
            this.LineFeedTypeStatus.Text = string.Empty;
            this.CursorStatusLable.Text = string.Empty;
            this.DocmentTypeStatus.Text = string.Empty;
            this.EncodeTypeStatus.Text = string.Empty;
            this.InsertModeStatus.Text = string.Empty;
        }

        void EditForm_EncodeChangeEventHandler(object sender, EventArgs e)
        {
            EditForm active = sender as EditForm;
            if (active == null)
                return;
            EncodeTypeStatus.Text = active.enc.EncodingName;
            EncodeToolStripMenuItem.DropDownItems.SwitchChckedItem(active.enc.EncodingName);
        }

        void EditForm_DocumentChangeTypeEventHandler(object sender, EventArgs e)
        {
            EditForm active = sender as EditForm;
            if (active == null)
                return;
            DocmentTypeStatus.Text = active.DocumentType == null ? Resources.DocumentModeNone : active.DocumentType;
            if(active.DocumentType == null)
                DocumentModeToolStripMenuItem.DropDownItems.SwitchChckedItem(Resources.DocumentModeNone);
            else
                DocumentModeToolStripMenuItem.DropDownItems.SwitchChckedItem(active.DocumentType);
        }

        void EditForm_LinefeedTypeChangeEventHandler(object sender, EventArgs e)
        {
            EditForm active = sender as EditForm;
            if (active == null)
                return;
            LineFeedTypeStatus.Text = active.linefeed.ToString();
            LineFeedToolStripMenuItem.DropDownItems.SwitchChckedItem(active.linefeed.ToString());
        }

        private void ConfigMenuItem_Click(object sender, EventArgs e)
        {
            ConfigForm cfgform = new ConfigForm(this.plugins);
            cfgform.ConfigChangeEvent += new ConfigChangeEventHandler(cfgform_ConfigChangeEvent);
            cfgform.ShowDialog();
            cfgform.Dispose();
        }

        void cfgform_ConfigChangeEvent(object sender, EventArgs e)
        {
            for (int i = 0; i < this.dockPanel1.Contents.Count; i++)
            {
                EditForm active = this.dockPanel1.Contents[i] as EditForm;
                if (active == null)
                    continue;
                FooTextBox fooTextBox = active.fooTextBox1;
                fooTextBox.TokenToColor = this.cfg.Token2Color;
                if (fooTextBox.LineBreak != this.cfg.WordRap)
                    fooTextBox.LineBreak = this.cfg.WordRap;
                if(fooTextBox.TabStops != this.cfg.TabStops)
                    fooTextBox.TabStops = this.cfg.TabStops;
                if (fooTextBox.DrawCaretLine != this.cfg.DrawLine)
                    fooTextBox.DrawCaretLine = this.cfg.DrawLine;
                if (fooTextBox.UrlMark != this.cfg.UrlMark)
                    fooTextBox.UrlMark = this.cfg.UrlMark;
                if (fooTextBox.Font.Name != this.cfg.FontName || fooTextBox.Font.Size != this.cfg.FontSize)
                    fooTextBox.Font = new Font(this.cfg.FontName, this.cfg.FontSize);
                if (fooTextBox.DrawLineNumber != this.cfg.DrawLineNumber)
                    fooTextBox.DrawLineNumber = this.cfg.DrawLineNumber;
                active.fooTextBox1.Refresh();
            }
        }

        void SetProgressBarStatus(ProgressState type)
        {
            switch (type)
            {
                case ProgressState.Start:
                    this.ProgressBarStatus.Visible = true;
                    this.ProgressBarStatus.Style = ProgressBarStyle.Marquee;
                    this.ProgressBarStatus.MarqueeAnimationSpeed = 100;
                    this.ProgressBarStatus.Value = 50;
                    this.ProgressBarStatus.Minimum = 0;
                    this.ProgressBarStatus.Maximum = 100;
                    this.statusStrip1.Refresh();
                    break;
                case ProgressState.Complete:
                    this.ProgressBarStatus.Visible = false;
                    break;
            }
        }

        void fooTextBox1_CaretMoved(object sender, EventArgs e)
        {
            FooTextBox textbox = sender as FooTextBox;
            EditForm active = textbox.Parent as EditForm;
            this.BeginInvoke(new Action(()=>{
                this.SetCaretStatus(active);
            }));
        }

        void editor_CrateEditFromEvent(object sender, EditFormEventArgs e)
        {
            EditForm EditForm = e.edit;

            EditForm.fooTextBox1.Document.LoadProgress += new ProgressEventHandler(Document_LoadProgress);
            EditForm.fooTextBox1.Document.SaveProgress += new ProgressEventHandler(Document_SaveProgress);
            EditForm.fooTextBox1.MouseClick += new MouseEventHandler(fooTextBox1_MouseClick);
            EditForm.fooTextBox1.CaretMoved += new EventHandler(fooTextBox1_CaretMoved);
            EditForm.fooTextBox1.InsetModeChange += new InsertModeChangeEventHandler(fooTextBox1_InsetModeChange);

            EditForm.LinefeedTypeChangeEvent += new LinefeedTypeChangeEventHandler(EditForm_LinefeedTypeChangeEventHandler);
            EditForm.DocumentChangeTypeEvent += new DocumentTypeChangeEventHandler(EditForm_DocumentChangeTypeEventHandler);
            EditForm.EncodeChangeEvent += new EncodeChangeEventHandler(EditForm_EncodeChangeEventHandler);

            EditForm.FormClosing += new FormClosingEventHandler(EditForm_FormClosing);

            EditForm.fooTextBox1.DragDrop += this.EditForm_DragDrop;
            EditForm.fooTextBox1.DragEnter += this.EditForm_DragEnter;
            EditForm.ContextMenuStrip = this.contextMenuStrip1;
        }

        void Document_LoadProgress(object sender, ProgressEventArgs e)
        {
            this.BeginInvoke(new Action(() =>
            {
                if (e.state == ProgressState.Start)
                    this.menuStrip1.Enabled = false;
                else if (e.state == ProgressState.Complete)
                    this.menuStrip1.Enabled = true;
                SetProgressBarStatus(e.state);
                TaskBar taskbar = TaskBar.GetInstance();
                taskbar.SetProgressState(e.state);
            }));
        }

        void Document_SaveProgress(object sender, ProgressEventArgs e)
        {
            this.BeginInvoke(new Action(() =>
            {
                if (e.state == ProgressState.Start)
                {
                    this.OpenToolStripMenuItem.Enabled = false;
                    this.SaveToolStripMenuItem.Enabled = false;
                    this.OverwriteToolStripMenuItem.Enabled = false;
                }
                else if (e.state == ProgressState.Complete)
                {
                    this.OpenToolStripMenuItem.Enabled = true;
                    this.SaveToolStripMenuItem.Enabled = true;
                    this.OverwriteToolStripMenuItem.Enabled = true;
                }
                SetProgressBarStatus(e.state);
                TaskBar taskbar = TaskBar.GetInstance();
                taskbar.SetProgressState(e.state);
            }));
        }

        void fooTextBox1_InsetModeChange(object sender, EventArgs e)
        {
            FooTextBox textbox = sender as FooTextBox;
            this.InsertModeStatus.Text = textbox.InsertMode ? Resources.InsertModeText : Resources.OverwriteModexText;
        }

        void fooTextBox1_MouseClick(object sender, MouseEventArgs e)
        {
            FooTextBox textbox = sender as FooTextBox;
            EditForm active = textbox.Parent as EditForm;
            this.SetCaretStatus(active);
        }

        private void 縦に分割ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.dockPanel1.LayoutDocument(LayoutFlag.Vertical);
        }

        private void 横に分割ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.dockPanel1.LayoutDocument(LayoutFlag.Horizontal);
        }

        private void カスケードToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.dockPanel1.LayoutDocument(LayoutFlag.Tab);
        }

        private void 作業環境の保存ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.SaveCurrentStates();
        }

        void RecentFile_RecentFileAddEventHandler(object sender, RecentFileUpdateArgs e)
        {
            string filepath = e.lastUpdatedPath;
            TaskBar taskbar = TaskBar.GetInstance();
            switch (e.type)
            {
                case RecentFileUpdateType.Add:
                    ToolStripMenuItem item = new ToolStripMenuItem();
                    item.Text = filepath.TrimFullPath();
                    item.Tag = filepath;
                    item.Click += new EventHandler(RecentFile_menuitem_Click);
                    RecentToolStripMenuItem.DropDownItems.Add(item);
                    break;
                case RecentFileUpdateType.Insert:
                    ToolStripMenuItem newItem = new ToolStripMenuItem();
                    newItem.Tag = filepath;
                    newItem.Text = filepath.TrimFullPath();
                    newItem.Click += this.RecentFile_menuitem_Click;
                    this.RecentToolStripMenuItem.DropDownItems.Insert(0, newItem);
                    break;
                case RecentFileUpdateType.Remove:
                    ToolStripItem found = this.RecentToolStripMenuItem.DropDownItems.FindItemByText(filepath.TrimFullPath());
                    if (found != null)
                        this.RecentToolStripMenuItem.DropDownItems.Remove(found);
                    break;
                case RecentFileUpdateType.Clear:
                    RecentToolStripMenuItem.DropDownItems.Clear();
                    break;
            }
        }

        private string SetHeader(EditForm edit)
        {
            return Path.GetFileName(edit.filepath);
        }

        void SetCaretStatus(EditForm active)
        {
            if (active == null)
            {
                CursorStatusLable.Text = string.Format(Resources.CursorPostion, 0, 0);
                return;
            }

            TextPoint tp = active.fooTextBox1.CaretPostion;
            CursorStatusLable.Text = string.Format(Resources.CursorPostion, tp.row + 1, tp.col + 1);
        }

        void ReadStdin()
        {
            EditForm active = this.dockPanel1.ActiveContent as EditForm;
            if (active == null)
                return;
            TextReader sr = Console.In;            //MSDNのConsoleクラスによると閉じる必要はないらしい
            try
            {
                active.fooTextBox1.Document.Load(sr);
            }
            catch (IOException)     //コマンドプロンプトから開くと例外が発生する
            {
            }
        }

        private void SaveCurrentStates()
        {
            for (int i = 0; i < this.dockPanel1.Contents.Count; i++)
            {
                EditForm active = this.dockPanel1.Contents[i] as EditForm;
                if (active != null)
                {
                    string recoveyDataFilePath = string.Format(Config.ApplicationFolder + "\\" + Resources.RecoveryData, Process.GetCurrentProcess().Id, active.Handle.ToInt32());
                    string recoveryStateFilePath = string.Format(Config.ApplicationFolder + "\\" + Resources.RecoveryState, Process.GetCurrentProcess().Id, active.Handle.ToInt32());
                    this.editor.SaveCurrentState(active,recoveryStateFilePath,recoveyDataFilePath);
                }
            }
        }

        private bool RecoveryEvent()
        {
            string recoveryStateFilePattern = string.Format(Resources.RecoveryState, "*","");
            if (Directory.Exists(Config.ApplicationFolder) == false)
                return false;
            string[] files = Directory.GetFiles(Config.ApplicationFolder, recoveryStateFilePattern);
            if (files.Length > 0 && MessageBox.Show(Resources.RecoveryConfirm, "", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.No)
            {
                for (int i = 0; i < files.Length; i++)
                    File.Delete(files[i]);
                return true;
            }
            for (int i = 0; i < files.Length; i++)
            {
                this.editor.LoadCurrentState(files[i]);
                File.Delete(files[i]);
            }
            return false;
        }

        private void BulidCodePageList()
        {
            EditForm activeForm = this.dockPanel1.ActiveDocument as EditForm;

            List<ToolStripMenuItem> list = new List<ToolStripMenuItem>();
            foreach (EncodingInfo info in Encoding.GetEncodings())
            {
                ToolStripMenuItem item = new ToolStripMenuItem();
                string encodeName = info.DisplayName;
                if (activeForm != null && activeForm.enc.EncodingName == encodeName)
                    item.Checked = true;
                item.Text = encodeName;
                item.Tag = info.Name;
                item.Click += new EventHandler(CodeSelect_menuitem_Click);
                list.Add(item);
            }
            list.Sort((x, y) => { return x.Text.CompareTo(y.Text); });
            EncodeToolStripMenuItem.DropDownItems.Clear();
            EncodeToolStripMenuItem.DropDownItems.AddRange(list.ToArray());
            list.Clear();
        }

        private void BuildDocumentModeList()
        {
            EditForm activeForm = this.dockPanel1.ActiveDocument as EditForm;

            List<ToolStripMenuItem> list = new List<ToolStripMenuItem>();

            ToolStripMenuItem item;
            foreach (string docmode in this.cfg.SyntaxDefinitions.Keys)
            {
                item = new ToolStripMenuItem();
                if (activeForm != null && activeForm.DocumentType == docmode)
                    item.Checked = true;
                item.Text = docmode;
                item.Click += new EventHandler(DocumentModeMenuClick);
                list.Add(item);
            }
            item = new ToolStripMenuItem();
            if (activeForm != null && activeForm.DocumentType == null)
                item.Checked = true;            
            item.Text = Resources.DocumentModeNone;
            item.Click += new EventHandler(DocumentModeMenuClick);
            list.Add(item);

            DocumentModeToolStripMenuItem.DropDownItems.Clear();
            DocumentModeToolStripMenuItem.DropDownItems.AddRange(list.ToArray());
            list.Clear();
        }

        private void EncodeToolStripMenuItem_DropDownOpening(object sender, EventArgs e)
        {
            if(this.EncodeToolStripMenuItem.DropDownItems.Count == 1)
                BulidCodePageList();
        }

        private void DocumentModeToolStripMenuItem_DropDownOpening(object sender, EventArgs e)
        {
            if(this.DocumentModeToolStripMenuItem.DropDownItems.Count == 1)
                BuildDocumentModeList();
        }

    }

    class UserOperationException : Exception
    {
        public UserOperationException(string m) : base(m)
        {
        }
    }


    enum LayoutFlag
    {
        Vertical,
        Horizontal,
        Tab,
    }

    static class DockPanelExtenstion
    {
        public static void LayoutDocument(this DockPanel panel, LayoutFlag flag)
        {
            var Documents = from DockContent p in panel.Contents
                            where p.DockState == DockState.Document
                            select p;
            int DocumentCount = Documents.Count();
            DockContent prevDocument = Documents.First();

            if (DocumentCount == 0)
                return;

            DockAlignment align = DockAlignment.Top;
            switch (flag)
            {
                case LayoutFlag.Horizontal:
                    align = DockAlignment.Right;
                    break;
                case LayoutFlag.Vertical:
                    align = DockAlignment.Bottom;
                    break;
            }

            panel.SuspendLayout();

            if (flag != LayoutFlag.Tab)
            {
                foreach (DockContent p in Documents)
                {
                    if (p == prevDocument)
                        continue;
                    p.Show(prevDocument.Pane, align, 1 - 1 / (double)DocumentCount);
                    prevDocument = p;
                    DocumentCount--;
                }
            }
            else
            {
                foreach (DockContent p in Documents)
                    p.Show(prevDocument.Pane, null);
            }

            panel.ResumeLayout();
        }
    }
    static class StringExtension
    {
        public static string TrimFullPath(this string filepath)
        {
            if (filepath == null || filepath == "")
                return string.Empty;
            string DirectoryPart = Path.GetDirectoryName(filepath);
            string FilenamePart = Path.GetFileName(filepath);
            string[] slice = DirectoryPart.Split('\\');
            if (slice.Length > 3)
            {
                DirectoryPart = slice[0] + "\\..\\" + slice[slice.Length - 1];
                return DirectoryPart + "\\" + FilenamePart;
            }
            else
                return filepath;
        }
    }
    static class ToolStripItemCollectionExtensions
    {
        public static void SwitchChckedItem(this ToolStripItemCollection Collection,string ItemName)
        {
            foreach (ToolStripItem item in Collection)
            {
                if (item is ToolStripSeparator) //セパレーターを除外する
                    continue;
                ToolStripMenuItem menuitem = (ToolStripMenuItem)item;
                if (menuitem.Checked == true)
                    menuitem.Checked = false;
                if (menuitem.Text == ItemName)
                    menuitem.Checked = true;
            }
        }

        public static ToolStripItem FindItemByText(this ToolStripItemCollection Collection, string text)
        {
            foreach (ToolStripItem item in Collection)
            {
                if (item is ToolStripSeparator) //セパレーターを除外する
                    continue;
                ToolStripMenuItem menuitem = (ToolStripMenuItem)item;
                if (menuitem.Text == text)
                    return item;
            }
            return null;
        }
    }

}
