using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.ComponentModel;

namespace CaLib.User
{
	public delegate void HotkeyEventHandler();

	public class Hotkey
	{
		IntPtr Handle_;

		public class Input
		{
			/// <summary>
			/// ホットキーが押下されたときに呼ばれるイベント
			/// </summary>
			public readonly HotkeyEventHandler hander_;

			/// <summary>
			/// ホットキー
			/// </summary>
			public System.Windows.Forms.Keys key_ { get; set; }


			public int fsModifier
			{
				get
				{
					int value = 0;

					System.Windows.Forms.Keys modifiers = this.key_ & System.Windows.Forms.Keys.Modifiers;

					if ((modifiers & System.Windows.Forms.Keys.Alt) != 0)
						value |= WinApi.User32.MOD_ALT;

					if ((modifiers & System.Windows.Forms.Keys.Control) != 0)
						value |= WinApi.User32.MOD_CONTROL;

					if ((modifiers & System.Windows.Forms.Keys.Shift) != 0)
						value |= WinApi.User32.MOD_SHIFT;

					return value;
				}
			}

			public int vk
			{
				get
				{
					System.Windows.Forms.Keys modifiers = this.key_ & System.Windows.Forms.Keys.Modifiers;
					modifiers = ~modifiers;
					System.Windows.Forms.Keys vkey = this.key_ & modifiers;
					return (int)vkey;
				}
			}

			public Input()
			{
				this.key_ = System.Windows.Forms.Keys.None;
			}

			public Input(System.Windows.Forms.Keys s, HotkeyEventHandler hander)
			{
				this.key_ = s;
				this.hander_ = hander;
			}
		}

		/// <summary>
		/// keyはHOTKEY_ID（0x0000～0xbfff）。値はキー種別。
		/// </summary>
		Dictionary<int, Input> registeredKeies_ = new Dictionary<int, Input>();

		public Hotkey(IntPtr Handle)
		{
			this.Handle_ = Handle;
		}


		public bool Register(int hotkeyId, Input key)
		{
			int ret = WinApi.User32.RegisterHotKey(this.Handle_, hotkeyId, key.fsModifier, key.vk);

			if (ret==0)
			{
				return false;
			}

			registeredKeies_[hotkeyId] = key;

			return true;
		}

		public bool Clear()
		{
			if (registeredKeies_.Count < 1)
				return true;

			foreach (int id in registeredKeies_.Keys)
			{
				int ret = WinApi.User32.UnregisterHotKey(this.Handle_, id);
				if (ret == 0)
				{
					return false;
				}
			}


			registeredKeies_.Clear();
			return true;
		}

		int IsHotkey(System.Windows.Forms.Message m)
		{
			if (m.Msg != (int)WinApi.Message.id.WM_HOTKEY)
			{
				return -1;
			}

			int id = (int)m.WParam;
			if (!registeredKeies_.ContainsKey(id))
			{
				return -1;
			}

			return id;
		}

		/// <summary>
		/// ホットキーが押されたときに呼ばれます
		/// </summary>
		/// <param name="m"></param>
		public void OnKeyDown(System.Windows.Forms.Message m)
		{
			int hotkeyId = this.IsHotkey(m);
			if (hotkeyId < 0)
			{
				return;
			}

			Debug.WriteLine(string.Format("HotKey={0}", hotkeyId));

			Input ipt = registeredKeies_[hotkeyId];
			ipt.hander_();
		}
	}
}
