public override void HandleGameKey(IStateOwner pOwner, GameKeys g)
        {
            if (HandleBlockGroupKey(pOwner, g))
            {
                return;
            }


            if (g == GameKeys.GameKey_RotateCW || g == GameKeys.GameKey_RotateCCW)
            {
                bool ccw = g == GameKeys.GameKey_RotateCCW;
                foreach (var activeitem in PlayField.BlockGroups)
                {
                    if (!activeitem.Controllable)
                    {
                        continue;
                    }
                    if (PlayField.CanRotate(activeitem, ccw))
                    {
                        PerformRotation(pOwner, activeitem, ccw);
                    }
                    else if (this.GameOptions.AllowWallKicks)

                    {
                        //we will add up to 3 and subtract up to 3 to the X coordinate. if any say we can rotate then we proceed with allowing the rotation.

                        int[] checkoffsets = new int[] { 1, -1, 2, -2, 3, -3 };


                        int     OriginalPos = activeitem.X;
                        Boolean revertpos   = true;

                        foreach (int currentoffset in checkoffsets)
                        {
                            if (currentoffset == 0)
                            {
                                continue;
                            }
                            activeitem.X = OriginalPos + currentoffset;
                            if (PlayField.CanRotate(activeitem, ccw))
                            {
                                PerformRotation(pOwner, activeitem, ccw);
                                revertpos = false;
                                break;
                            }
                        }

                        if (revertpos)
                        {
                            activeitem.X = OriginalPos;
                        }
                    }
                }
            }
            else if (g == GameKeys.GameKey_Down)
            {
                HandleActiveGroups(pOwner, true);
            }
            else if (g == GameKeys.GameKey_Drop)
            {
                //drop all active groups.
                Nomino FirstGroup = PlayField.BlockGroups.FirstOrDefault();



                if (FirstGroup != null)
                {
                    //store the block positions for each block in the nomino.


                    foreach (var activeitem in PlayField.BlockGroups)
                    {
                        if (!activeitem.Controllable)
                        {
                            continue;
                        }
                        List <Tuple <BCPoint, NominoElement> > StartBlockPositions = new List <Tuple <BCPoint, NominoElement> >();
                        List <Tuple <BCPoint, NominoElement> > EndBlockPositions   = new List <Tuple <BCPoint, NominoElement> >();
                        foreach (var element in activeitem)
                        {
                            StartBlockPositions.Add(new Tuple <BCPoint, NominoElement>(new BCPoint(activeitem.X + element.X, activeitem.Y + element.Y), element));
                        }
                        int dropqty = 0;
                        var ghosted = GetGhostDrop(pOwner, activeitem, out dropqty, 0);
                        foreach (var element in ghosted)
                        {
                            EndBlockPositions.Add(new Tuple <BCPoint, NominoElement>(new BCPoint(ghosted.X + element.X, ghosted.Y + element.Y), element));
                        }
                        GenerateDropParticles(StartBlockPositions, EndBlockPositions);
                        activeitem.X = ghosted.X;
                        activeitem.SetY(pOwner, ghosted.Y);
                        PlayField.SetGroupToField(activeitem);
                        PlayField.RemoveBlockGroup(activeitem);
                        if (GameStats is TetrisStatistics ts)
                        {
                            GameStats.AddScore((dropqty * (5 + (ts.LineCount / 10))));
                        }
                    }

                    pOwner.Feedback(0.6f, 200);
                    Sounds.PlaySound(pOwner.AudioThemeMan.BlockGroupPlace.Key, pOwner.Settings.std.EffectVolume);
                    GameHandler.ProcessFieldChange(this, pOwner, FirstGroup);
                    //ProcessFieldChangeWithScore(pOwner, FirstGroup);
                }
            }
            else if (g == GameKeys.GameKey_Right || g == GameKeys.GameKey_Left)
            {
                int XMove = g == GameKeys.GameKey_Right ? 1 : -1;
                foreach (var ActiveItem in PlayField.BlockGroups)
                {
                    if (!ActiveItem.Controllable)
                    {
                        continue;
                    }
                    if (PlayField.CanFit(ActiveItem, ActiveItem.X + XMove, ActiveItem.Y, false) == TetrisField.CanFitResultConstants.CanFit)
                    {
                        lastHorizontalMove = DateTime.Now;
                        ActiveItem.X      += XMove;
                        Sounds.PlaySound(pOwner.AudioThemeMan.BlockGroupMove.Key, pOwner.Settings.std.EffectVolume);
                        pOwner.Feedback(0.1f, 50);
                    }
                    else
                    {
                        Sounds.PlaySound(pOwner.AudioThemeMan.BlockStopped.Key, pOwner.Settings.std.EffectVolume);
                        pOwner.Feedback(0.4f, 75);
                    }
                }
            }
            else if (g == GameKeys.GameKey_Pause)
            {
                if (g == GameKeys.GameKey_Pause)
                {
                    pOwner.LastPausedTime = DateTime.Now;
                    pOwner.CurrentState   = new PauseGameState(pOwner, this);

                    var playing = Sounds.GetPlayingMusic_Active();
                    playing?.Pause();
                    Sounds.PlaySound(pOwner.AudioThemeMan.Pause.Key, pOwner.Settings.std.EffectVolume);
                }

                //pOwner.CurrentState = new PauseGameState(this);
            }
            else if (g == GameKeys.GameKey_Hold)
            {
                if (HoldBlock != null && !BlockHold)
                {
                    //if there is a holdblock, take it and put it into the gamefield and make the first active blockgroup the new holdblock,
                    //then set BlockHold to block it from being used until the next Tetromino is spawned.
                    Nomino FirstGroup = PlayField.BlockGroups.FirstOrDefault();
                    if (FirstGroup != null)
                    {
                        if (FirstGroup.Controllable)
                        {
                            PlayField.RemoveBlockGroup(FirstGroup);

                            PlayField.AddBlockGroup(HoldBlock);

                            //We probably should set the speed appropriately here for the level. As is it will retain the speed from whe nthe hold block was
                            //held.
                            PlayField.Theme.ApplyTheme(HoldBlock, GameHandler, PlayField, NominoTheme.ThemeApplicationReason.Normal);
                            HoldBlock.X = (int)(((float)PlayField.ColCount / 2) - ((float)HoldBlock.GroupExtents.Width / 2));
                            HoldBlock.SetY(pOwner, 0);
                            HoldBlock.HighestHeightValue = 0; //reset the highest height as well, so the falling animation doesn't goof
                            HoldBlock = FirstGroup;
                            Sounds.PlaySound(pOwner.AudioThemeMan.Hold.Key, pOwner.Settings.std.EffectVolume);
                            pOwner.Feedback(0.9f, 40);
                            BlockHold = true;
                        }
                    }
                }
                else if (!BlockHold)
                {
                    Nomino FirstGroup = PlayField.BlockGroups.FirstOrDefault();
                    if (FirstGroup != null)
                    {
                        if (FirstGroup.Controllable)
                        {
                            PlayField.RemoveBlockGroup(FirstGroup);
                            HoldBlock = FirstGroup;
                            BlockHold = true;
                            Sounds.PlaySound(pOwner.AudioThemeMan.Hold.Key, pOwner.Settings.std.EffectVolume);
                        }
                    }
                }
            }
            else if (g == GameKeys.GameKey_Debug1)
            {
                pOwner.CurrentState = new ShowHighScoresState(TetrisGame.ScoreMan["Standard"], pOwner.CurrentState);
            }
            else if (g == GameKeys.GameKey_Debug2)
            {
                OptionsMenuSettingsSelectorState OptionState = new OptionsMenuSettingsSelectorState(BackgroundDrawers.StandardImageBackgroundGDI.GetStandardBackgroundDrawer(),
                                                                                                    pOwner, pOwner.CurrentState);

                pOwner.CurrentState = OptionState;

                /*if (pOwner.CurrentState is StandardTetrisGameState)
                 * {
                 *  ((StandardTetrisGameState) pOwner.CurrentState).GameStats.Score += 1000;
                 * }*/
            }
            else if (g == GameKeys.GameKey_Debug3)
            {
                int  DesiredFontPixelHeight = (int)(pOwner.GameArea.Height * (23d / 644d));
                Font standardFont           = new Font(TetrisGame.RetroFont, DesiredFontPixelHeight, FontStyle.Bold, GraphicsUnit.Pixel);
                Font ItemFont = new Font(TetrisGame.RetroFont, (int)((float)DesiredFontPixelHeight * (3f / 4f)), FontStyle.Bold, GraphicsUnit.Pixel);
                //set state to a testing menu state.

                MenuState ms = new MenuState(BackgroundDrawers.StandardImageBackgroundGDI.GetStandardBackgroundDrawer());
                ms.StateHeader    = "This is a Menu";
                ms.HeaderTypeface = standardFont.Name;
                ms.HeaderTypeSize = standardFont.Size;

                MenuStateTextMenuItem returnitem = new MenuStateTextMenuItem();
                returnitem.FontFace  = ItemFont.Name;
                returnitem.FontSize  = ItemFont.Size;
                returnitem.Text      = "Return";
                returnitem.BackColor = Color.Transparent;
                returnitem.ForeColor = Color.DarkBlue;
                var OriginalState = pOwner.CurrentState;
                ms.MenuElements.Add(returnitem);

                var scaleitem = new MenuStateScaleMenuItem(pOwner);
                scaleitem.FontFace = ItemFont.Name;
                scaleitem.FontSize = ItemFont.Size;
                ms.MenuElements.Add(scaleitem);

                ms.MenuItemActivated += (obj, e) =>
                {
                    if (e.MenuElement == returnitem)
                    {
                        pOwner.CurrentState = OriginalState;
                    }
                };
                for (int i = 0; i < 8; i++)
                {
                    MenuStateTextMenuItem mts = new MenuStateTextMenuItem();
                    mts.FontFace  = ItemFont.Name;
                    mts.FontSize  = ItemFont.Size;
                    mts.BackColor = Color.Transparent;
                    mts.ForeColor = Color.Black;
                    mts.Text      = "Item " + i.ToString();
                    ms.MenuElements.Add(mts);
                }
                pOwner.CurrentState = ms;
            }
            else if (g == GameKeys.GameKey_Debug4)
            {
                if (pOwner is IGamePresenter gp)
                {
                    var _Present = gp.GetPresenter();
                    if (_Present.ai == null)
                    {
                        _Present.ai = new StandardNominoAI(pOwner);
                    }
                    else
                    {
                        _Present.ai.AbortAI();
                        _Present.ai = null;
                    }
                }
            }
        }