using System;
using System.Drawing;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Windows.Forms;
using Microsoft.Win32;
using FooEditEngine;
using FooEditEngine.Windows;
using FooEditor;
using FooEditor.Plugin;
using AutoComplete.Properties;
using Microsoft.WindowsAPICodePack.Dialogs;

namespace AutoComplete
{
    [Export(typeof(IPlugin))]
    class Filter : IPlugin
    {
        Editor editor;
        bool CollectDocumentWords;

        public void Initalize(Editor e)
        {
            editor = e;
            editor.CreatedEditFromEvent += new CreateEditFormEventHandler(editor_CratedEditFromEvent);
            
            RegistryKey regkey = Registry.CurrentUser.CreateSubKey(Config.RegAppPath + "\\AutoComplete");
            CollectDocumentWords = bool.Parse((string)regkey.GetValue("CollectDocumentWords", "false"));
            regkey.Close();

            ToolStripMenuItem item = (ToolStripMenuItem)e.RootMenuStrip.Items[3];
            item.DropDownItems.Insert(0, new ToolStripMenuItem("ドキュメントから補完候補を作成する", null, CreateCompleteItemFromDoc));
            item.DropDownItems.Insert(0, new ToolStripMenuItem("TAGから補完候補を作成する", null, CrateCompleteItemFromTAGS));
        }

        public void ClosedApp()
        {
            RegistryKey regkey = Registry.CurrentUser.CreateSubKey(Config.RegAppPath + "\\AutoComplete");
            regkey.SetValue("CollectDocumentWords", CollectDocumentWords);
            regkey.Close();
            return;
        }

        public void ShowConfigForm()
        {
            ConfigForm configForm = new ConfigForm();

            configForm.CollectWords = CollectDocumentWords;

            if (configForm.ShowDialog() == DialogResult.OK)
            {
                CollectDocumentWords = configForm.CollectWords;                
            }
            configForm.Dispose();
        }

        private void CreateCompleteItemFromDoc(object sender, EventArgs e)
        {
            EditForm active = editor.EditForm;
            if (active == null)
                return;

            AutocompleteBox box = (AutocompleteBox)active.CompleteBox;

            if(box != null)
                foreach (string s in active.fooTextBox1.LayoutLines)
                    CompleteHelper.AddCompleteWords(box, active.SynataxDefnition.Operators, s);
        }


        private void CrateCompleteItemFromTAGS(object sender, EventArgs e)
        {
            EditForm active = editor.EditForm;
            if (active == null)
                return;

            CustomFileDialog ofd;
            ofd = new CustomOpenFileDialogForVista();

            CommonFileDialogResult result = ofd.ShowDialog();
            string filepath = ofd.FileName;
            Encoding enc = ofd.FileEncoding;

            ofd.Dispose();

            if (result == CommonFileDialogResult.Cancel)
                return;

            AutocompleteBox box = active.CompleteBox;

            StreamReader sr = new StreamReader(filepath, enc);
            while (!sr.EndOfStream)
            {
                string[] tokens = sr.ReadLine().Split(new char[] { '\t' }, StringSplitOptions.RemoveEmptyEntries);
                if (tokens[0][0] == '!')
                    continue;
                if(box != null)
                    CompleteHelper.AddComleteWord(box, tokens[0]);
            }
            sr.Close();
        }


        void editor_CratedEditFromEvent(object sender, EditFormEventArgs e)
        {
            e.edit.DocumentChangeTypeEvent += new FooEditor.DocumentTypeChangeEventHandler(edit_DocumentChangeTypeEvent);
        }

        void edit_DocumentChangeTypeEvent(object sender, EventArgs e)
        {
            EditForm editForm = (EditForm)sender;

            if (editForm.DocumentType == null)
                return;

            if (editForm.CompleteBox == null)
            {
                AutocompleteBox box = new AutocompleteBox(editForm.fooTextBox1);
                box.ShowingCompleteBox = new ShowingCompleteBoxEnventHandler(OnPreShow);
                box.SelectItem = new SelectItemEventHandler(OnDoAutocomplete);
                box.Items = new CompleteCollection<ICompleteItem>();
                editForm.fooTextBox1.KeyPress += new KeyPressEventHandler(fooTextBox1_KeyPress);
                editForm.CompleteBox = box;
            }

            if (editForm.SynataxDefnition != null)
            {
                AutocompleteBox CompleteBox = editForm.CompleteBox;
                CompleteBox.Items.Clear();
                CompleteBox.Operators = editForm.SynataxDefnition.Operators;

                foreach (string s in editForm.SynataxDefnition.Keywords)
                    CompleteBox.Items.Add(new CompleteWord(s));
                foreach (string s in editForm.SynataxDefnition.Keywords2)
                    CompleteBox.Items.Add(new CompleteWord(s));
            }
        }

        void fooTextBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            AutocompleteBox box = editor.EditForm.CompleteBox;
            FooTextBox textbox = editor.EditForm.fooTextBox1;

            if (this.CollectDocumentWords == false)
                return;
            if (e.KeyChar == '\r')
            {
                int row = textbox.CaretPostion.row - 1;
                CompleteHelper.AddCompleteWords(box, editor.EditForm.SynataxDefnition.Operators, textbox.LayoutLines[row]);
            }
        }

        private void OnDoAutocomplete(object sender, SelectItemEventArgs e)
        {
            FooTextBox textbox = e.textbox;
            string inputing_word = e.inputing_word;
            string word = e.word;

            //キャレットは入力された文字の後ろにあるので、こうする
            int start = textbox.SelectionStart - inputing_word.Length;
            if (start < 0)
                start = 0;

            textbox.Document.Replace(start, inputing_word.Length, word);

            textbox.Refresh();
        }

        private void OnPreShow(object sender, ShowingCompleteBoxEventArgs e)
        {
            AutocompleteBox box = (AutocompleteBox)sender;

            int inputingIndex = e.textbox.SelectionStart - 1;
            if (inputingIndex < 0)
                inputingIndex = 0;

            e.inputedWord = CompleteHelper.GetWord(e.textbox.Document, inputingIndex, box.Operators) + e.keyChar;

            for (int i = 0; i < box.Items.Count; i++)
            {
                CompleteWord item = (CompleteWord)box.Items[i];
                if (item.word.StartsWith(e.inputedWord))
                {
                    e.foundIndex = i;
                    break;
                }
            }
        }

    }
}
