using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Xml;
using System.Windows.Forms;
using System.Drawing;
using System.Diagnostics;
using ClipClop.Model;

namespace ClipClop.User
{
    //デリゲートの宣言
    public delegate void StringPasteEventHandler(string message);

	/// <summary>
	/// 定義ファイルから読み込んだアイテムを表示するコンテキストメニュークラス
	/// </summary>
	public class DynamicContextMenuStrip : System.Windows.Forms.ContextMenuStrip
	{
		AplSetting aplSetting_;

        IntPtr lastAvtiveWindow_;

		public AplSetting AplSetting
		{
			set
			{
				this.aplSetting_ = value;
			}
		}

        public IntPtr LastAvtiveWindow
        {
            set
            {
                this.lastAvtiveWindow_ = value;
            }
        }

		public DynamicContextMenuStrip() : base()
		{
		}

		public DynamicContextMenuStrip(IContainer container)
			: base(container)
		{
		}

        void StringPasteEventHandler(string message)
        {
            if (this.lastAvtiveWindow_ == IntPtr.Zero)
            {
                return;
            }

#if DEBUG
            StringBuilder sb = new StringBuilder(512);
            WinApi.User32.GetWindowText(this.lastAvtiveWindow_, sb, sb.Capacity);
            Debug.WriteLine(string.Format("paste to \"{0}\", {1}", sb.ToString(), message));
#endif

            WinApi.User32.SetForegroundWindow(this.lastAvtiveWindow_);
            WinApi.User32.SendMessage(this.lastAvtiveWindow_, (int)WinApi.Message.id.WM_PASTE, IntPtr.Zero, IntPtr.Zero);
        }

		//protected override void WndProc(ref Message m)
		//{
		//    base.WndProc(ref m);
		//}

		/// <summary>
		/// メニュー表示時に親ウィンドウが非表示だったかどうか
		/// </summary>
		//public bool ParentVisible { get; set; }


        public void ConstructMenu(ContextMenuSettingManager settingManager, ListBox.ObjectCollection history)
		{
			this.Items.Clear();
			//this.menuEventHanders_.Clear();

			if (null == settingManager.RootNode)
				return;

            RecursiveConstructMenu(settingManager.RootNode, this.Items, history);
		}

        void RecursiveConstructMenu(XmlNode parentnode, ToolStripItemCollection items, ListBox.ObjectCollection history)
		{
			foreach (XmlNode childXmlNode in parentnode.ChildNodes)
			{
				if (ContextMenuSettingHelper.GetSettingType(childXmlNode) == ContextMenuSettingDefinition.SettingType.separator)
				{
					items.Add( new ToolStripSeparator() );
					continue;
				}

				ToolStripMenuItemEx menu = new ToolStripMenuItemEx(childXmlNode,this.aplSetting_);
                menu.OnStringPaste += this.StringPasteEventHandler;

				// クリップボード履歴
				if (ContextMenuSettingHelper.GetSettingType(childXmlNode) == ContextMenuSettingDefinition.SettingType.sentence 
					&& ContextMenuSettingHelper.GetMode(childXmlNode) == ContextMenuSettingDefinition.Mode.clipboardhistory)
				{
                    foreach (object obj in history)
                    {
                        if (global::ClipClop.Properties.Settings.Default.MaxHistoryInMenu <= menu.DropDownItems.Count)
                            break;

                        string s = obj as string;
                        if (string.IsNullOrEmpty(s))
                            continue;

                        ToolStripMenuItemHistory menuHistory = new ToolStripMenuItemHistory(s);
                        menuHistory.OnStringPaste += this.StringPasteEventHandler;
                        menu.DropDownItems.Add(menuHistory);
                    }
				}

				items.Add(menu);

				// 再帰呼び出し
                RecursiveConstructMenu(childXmlNode, menu.DropDownItems, history);
			}
		}

        class ToolStripMenuItemPastable : ToolStripMenuItem
        {
            //イベントデリゲートの宣言
            public event StringPasteEventHandler OnStringPaste;

            public ToolStripMenuItemPastable(string text)
                : base(text)
            {
            }

            protected void PasteString(string str)
            {
                // リストに二つ入るけれど、リストで先頭と同じなら挿入しないようにした。
                Clipboard.SetDataObject(str, true);

                if (OnStringPaste != null)
                {
                    OnStringPaste(str);
                }
            }
        }




        class ToolStripMenuItemHistory : ToolStripMenuItemPastable
        {
            readonly string history_;
            public ToolStripMenuItemHistory(string history)
                : base(GetDisplayString(history))
            {
                this.history_ = history;
                base.Click += this.OnHistoryItemClickedEvent;
            }

            const string extensionMark_ = "...";

            static string GetDisplayString(string history)
            {
                string s = history.Replace(Environment.NewLine,"");

                if (s.Length <= global::ClipClop.Properties.Settings.Default.MaxHistoryItemLength)
                    return s;
                s = s.Substring(0, global::ClipClop.Properties.Settings.Default.MaxHistoryItemLength) + extensionMark_;
                return s;
            }

            /// <summary>
            /// クリップボード履歴メニューアイテムが選択されたら呼ばれる
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            public void OnHistoryItemClickedEvent(object sender, EventArgs e)
            {
                base.PasteString(this.history_);
            }
        }

        class ToolStripMenuItemEx : ToolStripMenuItemPastable
		{
			readonly XmlNode node_;

			readonly AplSetting aplSetting_;

			public ToolStripMenuItemEx(XmlNode node, AplSetting aplSetting)
				: base(ContextMenuSettingHelper.GetDisplayString(node))
			{
				this.node_ = node;
				this.aplSetting_ = aplSetting;
				base.Click += this.OnMenuEvent;
			}

			public ToolStripMenuItem CreatetMenu()
			{
				ToolStripMenuItem menu = new ToolStripMenuItem();
				return menu;
			}


			public void StartProcess(string exeString)
			{

				System.Diagnostics.Process process = null;
				try
				{
					process = System.Diagnostics.Process.Start(exeString);
				}
				catch (Exception exp)
				{
					Util.ShowError(global::ClipClop.Properties.Resources.EF003 + Environment.NewLine + exp.Message + Environment.NewLine + exeString);
					return;
				}

				if (process == null)
				{
					Util.ShowError(global::ClipClop.Properties.Resources.EF003);
				}
			}

			/// <summary>
			/// メニューがクリックされた
			/// </summary>
			/// <param name="sender"></param>
			/// <param name="e"></param>
			public void OnMenuEvent(object sender, EventArgs e)
			{
				if (ContextMenuSettingDefinition.Sentence_ != node_.Name)
					return;

				ContextMenuSettingDefinition.Mode mode = ContextMenuSettingHelper.GetMode(this.node_);

				Debug.WriteLine(string.Format("{0},{1},{2}", ContextMenuSettingHelper.GetDisplayString(node_), ContextMenuSettingHelper.GetValue(node_), mode));

				switch (mode)
				{
					case ContextMenuSettingDefinition.Mode.execute:
						//Exe実行の場合

						string exeString = ContextMenuSettingHelper.GetExecuteString(node_);

						StartProcess(exeString);

						return;

					case ContextMenuSettingDefinition.Mode.editfile:
						StartProcess(this.aplSetting_.templateFilePath_);

						return;

                    case ContextMenuSettingDefinition.Mode.clipboardhistory:
                        return;
				}
				

				string value = ContextMenuSettingHelper.GetValueReplaced(node_, DateTime.Now);
                base.PasteString(value);
			}
		}

        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // DynamicContextMenuStrip
            // 
            this.ResumeLayout(false);

        }

		//protected override void WndProc(ref Message m)
		//{
		//    base.WndProc(ref m);
		//}

	}
}
