/// <summary>
        /// Low-level mouse hook procedure
        /// The system call this function every time a new mouse input event is
        /// about to be posted into a thread input queue. The mouse input can come
        /// from the local mouse driver or from calls to the mouse_event function.
        /// If the input comes from a call to mouse_event, the input was
        /// "injected". However, the WH_MOUSE_LL hook is not injected into another
        /// process. Instead, the context switches back to the process that
        /// installed the hook and it is called in its original context. Then the
        /// context switches back to the application that generated the event.
        /// </summary>
        /// <param name="nCode">
        /// The hook code passed to the current hook procedure.
        /// When nCode equals HC_ACTION, the wParam and lParam parameters contain
        /// information about a mouse message.
        /// </param>
        /// <param name="wParam">
        /// This parameter can be one of the following messages:
        /// WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MOUSEMOVE, WM_MOUSEWHEEL,
        /// WM_MOUSEHWHEEL, WM_RBUTTONDOWN, or WM_RBUTTONUP.
        /// </param>
        /// <param name="lParam">Pointer to an MSLLHOOKSTRUCT structure.</param>
        /// <returns></returns>
        /// <see cref="http://msdn.microsoft.com/en-us/library/ms644986.aspx"/>
        public int LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0)
            {
                // Marshal the MSLLHOOKSTRUCT data from the callback lParam
                MSLLHOOKSTRUCT mouseLLHookStruct = (MSLLHOOKSTRUCT)
                                                   Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));

                // Get the mouse WM from the wParam parameter
                MouseMessage wmMouse = (MouseMessage)wParam;

                MouseMessage left  = (MouseMessage)WM_LBUTTONDOWN;
                MouseMessage right = (MouseMessage)WM_RBUTTONDOWN;
                if (wmMouse == left || wmMouse == right)/* It does the same thing as a panic they does */
                {
                    bufferObj.Clear();
                    WriteAndClearTuple_nTimer();
                }
            }

            // Pass the hook information to the next hook procedure in chain
            return(WindowsAPI.CallNextHookEx(hGlobalLLMouseHook, nCode, wParam, lParam));
        }
        public int LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0)
            {
                // Marshal the KeyboardHookStruct data from the callback lParam
                KBDLLHOOKSTRUCT keyboardLLHookStruct = (KBDLLHOOKSTRUCT)
                                                       Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));


                Keys            vkCode     = (Keys)keyboardLLHookStruct.vkCode;
                KeyboardMessage wmKeyboard = (KeyboardMessage)wParam; // Get the keyboard WM from the wParam parameter


                typeOfPressedKey = InputUtils.GetKeyType(vkCode);//Gets a type of pressed key

                TriggerFlagsInitialization(typeOfPressedKey, vkCode, wmKeyboard);

                if (typeOfPressedKey == "system")
                {
                    for (int i = 0; i < InputUtils.systemKeys.Length; i++)// Have to check every possible trigger key
                    {
                        TriggerFlags(vkCode, InputUtils.ReturnSystemKey(i), wmKeyboard, i);
                    }
                }


                if (wmKeyboard == keyUp || wmKeyboard == keyUpSys)
                {
                    mainController.LastKeyPressed_LiftOff(vkCode);
                }

                if (wmKeyboard == keyDown || wmKeyboard == keyDownSys)
                {
                    try
                    {
                        ExeUtils.AsyncGetExeID();
                    }
                    catch (Exception)
                    {
                        /* In case of failure keeps old one */
                    }

                    /* Sets up timer and stopwatch. Can't time timer */
                    if (!userLevelTimer.Enabled)
                    {
                        userLevelTimer.Enabled = true;
                        userLevelTimer.Start();
                        timer2.Start();
                    }

                    if (!inputStopWatch.IsRunning)
                    {
                        inputStopWatch.Start();
                    }
                    int timePassed = (int)inputStopWatch.ElapsedMilliseconds;

                    if (ExeUtils.isTrackable)
                    {
                        mainController.AddToInputBuffer(vkCode, timePassed, ExeUtils.exeID, typeOfPressedKey);
                    }

                    switch (typeOfPressedKey)
                    {
                    case "system":
                        /* in case there's stuff to do */
                        break;

                    case "panic":
                        bufferObj.Clear();
                        WriteAndClearTuple_nTimer();
                        break;

                    case "rule":
                        if (bufferObj.Count() > 0)
                        {
                            int key = 0;     /* WHEN BACKSPACE */
                            if (vkCode == Keys.Delete)
                            {
                                key = 1;     /* WHEN DELETE */
                            }

                            if (rules.OneWordValidation(vkCode, bufferObj))     /* Checks if space wasn't deleted. If it was just save to db */
                            {
                                SortTupleList();
                                WriteAndClearTuple_nTimer();
                            }

                            if (bufferObj.ValidateBounds(key))     /*  */
                            {
                                preDeleteBuffer.Add(bufferObj.GetInputForMistakes(vkCode));
                                tupleBuffer = rules.RuleKey(vkCode, tupleBuffer, bufferObj, (int)normalInputSW.ElapsedMilliseconds);
                                bufferObj.SendRuleKeys(vkCode);
                                bufferObj.ruleKeyPressed = true;
                            }
                            else
                            {
                                WriteAndClearTuple_nTimer();
                            }
                        }
                        break;

                    case "pointer":
                        string triggerFlag = TriggerFlags_Enabled_Keys();
                        if (triggerFlag != "Sys")
                        {
                            if (triggerFlag == "None")
                            {
                                bufferObj.SendRuleKeys(vkCode);
                            }
                            else if (triggerFlag == "Ctrl")
                            {
                                bufferObj.SendRuleKeys(vkCode, true);
                            }
                            WriteAndClearTuple();
                        }
                        break;

                    case "normal":

                        if (!flagArray.Contains(true))
                        {
                            if (bufferObj.ruleKeyPressed == true)
                            {
                                SortTupleList();

                                if (InputUtils.seperatorKeys.Contains(vkCode))    //space and rest of the buch
                                {
                                    WriteAndClearTuple_nTimer();
                                    Action(vkCode, wmKeyboard);
                                }
                                else
                                {
                                    string replaceWith = InputUtils.GetCharsFromKeys(vkCode);

                                    rules.NormalKey(tupleBuffer, replaceWith, (int)normalInputSW.ElapsedMilliseconds);
                                    Action(vkCode, wmKeyboard);
                                }
                            }
                            else
                            {
                                Action(vkCode, wmKeyboard);
                            }
                        }
                        else
                        {
                            WriteAndClearTuple_nTimer();
                        }
                        if (normalInputSW.IsRunning)
                        {
                            normalInputSW.Restart();
                        }
                        else
                        {
                            normalInputSW.Start();
                        }
                        break;

                    default:

                        break;
                    }
                    userLevelTimer.Stop();
                    userLevelTimer.Start();
                    inputStopWatch.Restart();
                }
            }
            return(WindowsAPI.CallNextHookEx(hGlobalLLKeyboardHook, nCode, wParam, lParam));
        }