using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Reflection;
using System.Windows.Forms;
using System.Windows.Forms.Design;

namespace Mesnac.Gui.Edit.Common
{
    public sealed class FormKeyHandler : IMessageFilter
    {
        const int keyPressedMessage = 0x100;
        const int leftMouseButtonDownMessage = 0x0202;

        private Host.HostSurfaceManager _hostSurfaceManager = null;

        readonly Dictionary<Keys, CommandWrapper> keyTable = new Dictionary<Keys, CommandWrapper>();
        public static bool inserted = false;
        public static void Insert(Host.HostSurfaceManager hsm)
        {
            inserted = true;
            Application.AddMessageFilter(new FormKeyHandler(hsm));
        }

        public FormKeyHandler(Host.HostSurfaceManager hsm)
        {
            this._hostSurfaceManager = hsm;
            // normal keys
            keyTable[Keys.Left] = new CommandWrapper(MenuCommands.KeyMoveLeft);
            keyTable[Keys.Right] = new CommandWrapper(MenuCommands.KeyMoveRight);
            keyTable[Keys.Up] = new CommandWrapper(MenuCommands.KeyMoveUp);
            keyTable[Keys.Down] = new CommandWrapper(MenuCommands.KeyMoveDown);
            keyTable[Keys.Tab] = new CommandWrapper(MenuCommands.KeySelectNext);
            keyTable[Keys.Delete]   = new CommandWrapper(MenuCommands.Delete);
            //keyTable[Keys.Back]   = new CommandWrapper(MenuCommands.Delete);

            // shift modified keys
            keyTable[Keys.Left | Keys.Shift] = new CommandWrapper(MenuCommands.KeySizeWidthDecrease);
            keyTable[Keys.Right | Keys.Shift] = new CommandWrapper(MenuCommands.KeySizeWidthIncrease);
            keyTable[Keys.Up | Keys.Shift] = new CommandWrapper(MenuCommands.KeySizeHeightDecrease);
            keyTable[Keys.Down | Keys.Shift] = new CommandWrapper(MenuCommands.KeySizeHeightIncrease);
            keyTable[Keys.Tab | Keys.Shift] = new CommandWrapper(MenuCommands.KeySelectPrevious);
            //keyTable[Keys.Delete| Keys.Shift]   = new CommandWrapper(MenuCommands.Delete);
            //keyTable[Keys.Back| Keys.Shift]   = new CommandWrapper(MenuCommands.Delete);

            // ctrl modified keys
            keyTable[Keys.Left | Keys.Control] = new CommandWrapper(MenuCommands.KeyNudgeLeft);
            keyTable[Keys.Right | Keys.Control] = new CommandWrapper(MenuCommands.KeyNudgeRight);
            keyTable[Keys.Up | Keys.Control] = new CommandWrapper(MenuCommands.KeyNudgeUp);
            keyTable[Keys.Down | Keys.Control] = new CommandWrapper(MenuCommands.KeyNudgeDown);

            // ctrl + shift modified keys
            keyTable[Keys.Left | Keys.Control | Keys.Shift] = new CommandWrapper(MenuCommands.KeyNudgeWidthDecrease);
            keyTable[Keys.Right | Keys.Control | Keys.Shift] = new CommandWrapper(MenuCommands.KeyNudgeWidthIncrease);
            keyTable[Keys.Up | Keys.Control | Keys.Shift] = new CommandWrapper(MenuCommands.KeyNudgeHeightDecrease);
            keyTable[Keys.Down | Keys.Control | Keys.Shift] = new CommandWrapper(MenuCommands.KeyNudgeHeightIncrease);
        }

        public bool PreFilterMessage(ref Message m)
        {
            if (m.Msg != keyPressedMessage /*&& m.Msg != leftMouseButtonDownMessage*/)
            {
                return false;
            }
            if (this._hostSurfaceManager == null || this._hostSurfaceManager.ActiveDesignSurface == null)
            {
                return false;
            }

            Control originControl = Control.FromChildHandle(m.HWnd);

            if (originControl != this._hostSurfaceManager.ActiveDesignSurface.View)
            {
                return false;
            }

            Keys keyPressed = (Keys)m.WParam.ToInt32() | Control.ModifierKeys;

            CommandWrapper commandWrapper;
            if (keyTable.TryGetValue(keyPressed, out commandWrapper))
            {
                Console.WriteLine("Run menu command: " + commandWrapper.CommandID);

                if (DelIntakeControl.DelControl(_hostSurfaceManager, commandWrapper.CommandID.ID))
                {
                    IMenuCommandService menuCommandService = (IMenuCommandService)this._hostSurfaceManager.ActiveDesignSurface.GetService(typeof(IMenuCommandService));
                    menuCommandService.GlobalInvoke(commandWrapper.CommandID);
                }

                return true;
            }

            return false;
        }


        sealed class CommandWrapper
        {
            CommandID commandID;
            bool restoreSelection;

            public CommandID CommandID
            {
                get
                {
                    return commandID;
                }
            }

            public bool RestoreSelection
            {
                get
                {
                    return restoreSelection;
                }
            }

            public CommandWrapper(CommandID commandID)
                : this(commandID, false)
            {
            }
            public CommandWrapper(CommandID commandID, bool restoreSelection)
            {
                this.commandID = commandID;
                this.restoreSelection = restoreSelection;
            }
        }
    }
}