using Ck_Objects;
using SpriteEditor_2017;
using System;
using System.CodeDom;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Wordinator;

namespace Bombing_Math
{

    public partial class formBombingMath : PerPixelForm.PerPixelAlphaForm
    {
        public static formBombingMath instance = null;

        static List<classExplosion> lstExplosions = new List<classExplosion>();
        static List<classMathProblem> lstProblems
        {
            get { return classMathProblem.lstProblems; }
        }

        public static Ck_Objects.classSweepAndPrune cSP = new Ck_Objects.classSweepAndPrune();
        public static bool _bolDeveloper = false;
        public static bool bolDeveloper
        {
            get
            {
                return _bolDeveloper;
            }
        }




        public class classExponentialBomb
        {
            static public List<classExponentialBomb> lstExponentialBombs = new List<classExponentialBomb>();
            public Point ptCenter = new Point();
            public int intSize = 0;
            classEventController.classEventTicket cEventTicket_Grow = null;

            public static Bitmap bmpForm
            {
                get { return formBombingMath.bmpWorking; }
            }

            public classExponentialBomb()
            {
                cEventTicket_Grow = formBombingMath.cEC.Ticket("Exponential Bomb", 125, tmrGrow_Tick);
            }
            void tmrGrow_Tick(object sender, EventArgs e)
            {
                intSize += bmpForm.Width / 10;

                List<classSweepAndPrune.classElement> lstEleFound = cSP.Search(recDamage);
                for (int intProblemsFound = 0; intProblemsFound < lstEleFound.Count; intProblemsFound++)
                {
                    classSweepAndPrune.classElement cEleFound = lstEleFound[intProblemsFound];
                    if (cEleFound.obj != null)
                    {
                        try
                        {
                            classMathProblem cProblemFound = (classMathProblem)cEleFound.obj;
                            cProblemFound.ProblemSolved(false);
                        }
                        catch (Exception)
                        {
                        }
                    }

                }

                if (intSize > bmpForm.Width / 4)
                {
                    lstExponentialBombs.Remove(this);
                    return;
                }
                cEventTicket_Grow.Reschedule();
            }

            public Rectangle recDamage
            {
                get
                {
                    Rectangle recDestroy = new Rectangle(ptCenter.X - intSize,
                                                                    ptCenter.Y - intSize,
                                                                    2 * intSize,
                                                                    2 * intSize);
                    return recDestroy;

                }
            }

        }

        public List<classExponentialBomb> lstExponentialBombs
        {
            get { return classExponentialBomb.lstExponentialBombs; }
        }


        static int Tools_NumTypes
        {
            get
            {
                return Enum.GetNames(typeof(enuTools)).Length;
            }
        }

        static int[] _arrTools_Inventory = null;
        public static int[] arrTools_Inventory
        {
            get
            {
                if (_arrTools_Inventory == null)
                {
                    _arrTools_Inventory = new int[Tools_NumTypes];
                }
                return _arrTools_Inventory;
            }
        }

        static classSweepAndPrune.classElement cSPEle_Grab = new classSweepAndPrune.classElement();
        //static classSweepAndPrune.classElement cSPEle_Resize = new classSweepAndPrune.classElement();

        static List<classSweepAndPrune.classElement> _lstSPEle_ToolButtons = new List<classSweepAndPrune.classElement>();
        public static List<classSweepAndPrune.classElement> lstSPEle_ToolButtons
        {
            get
            {
                if (_lstSPEle_ToolButtons.Count == 0)
                {
                    _lstSPEle_ToolButtons = new List<classSweepAndPrune.classElement>();
                    for (int intToolCounter = 0; intToolCounter < Tools_NumTypes; intToolCounter++)
                    {
                        _lstSPEle_ToolButtons.Add(new classSweepAndPrune.classElement());
                    }
                }
                return _lstSPEle_ToolButtons;
            }
        }

        static Bitmap[] _arrImages_Tools = null;
        public static Bitmap[] arrImages_Tools
        {
            get
            {
                if (_arrImages_Tools == null)
                {
                    _arrImages_Tools = new Bitmap[Tools_NumTypes];

                    _arrImages_Tools[(int)enuTools.Bomb] = (Bitmap)new Bitmap(Properties.Resources.Tool_Bomb);
                    _arrImages_Tools[(int)enuTools.Bomb].MakeTransparent(_arrImages_Tools[(int)enuTools.Bomb].GetPixel(0, 0));

                    _arrImages_Tools[(int)enuTools.ExponentialBomb] = (Bitmap)new Bitmap(Properties.Resources.Tool_ExponentialBomb);
                    _arrImages_Tools[(int)enuTools.ExponentialBomb].MakeTransparent(_arrImages_Tools[(int)enuTools.ExponentialBomb].GetPixel(0, 0));

                    _arrImages_Tools[(int)enuTools.SpyGlass] = (Bitmap)new Bitmap(Properties.Resources.Tool_SpyGlass);
                    _arrImages_Tools[(int)enuTools.SpyGlass].MakeTransparent(_arrImages_Tools[(int)enuTools.SpyGlass].GetPixel(0, 0));

                    _arrImages_Tools[(int)enuTools.TimePiece] = (Bitmap)new Bitmap(Properties.Resources.Tool_TimePiece);
                    _arrImages_Tools[(int)enuTools.TimePiece].MakeTransparent(_arrImages_Tools[(int)enuTools.TimePiece].GetPixel(0, 0));
                }
                return _arrImages_Tools;
            }
        }

        public static Rectangle recPlayingField = new Rectangle();
        public static Rectangle recColumn = new Rectangle();
        public static Rectangle recScore = new Rectangle();
        public static Rectangle recLevel = new Rectangle();
        public static Rectangle recNumRemaining = new Rectangle();
        public static Rectangle recUserInput = new Rectangle();

        static List<Bitmap> lstBitmaps_Scenery = new List<Bitmap>();
        static Bitmap bmpScenery
        {
            get
            {
                if (lstBitmaps_Scenery.Count == 0)
                {
                    string strDirectory = System.IO.Directory.GetCurrentDirectory() + "\\";

                    string[] arrImageScenery = System.IO.Directory.GetFiles(strDirectory, "scene*.png");
                    lstBitmaps_Scenery.Clear();
                    for (int intImageCounter = 0; intImageCounter < arrImageScenery.Length; intImageCounter++)
                    {
                        lstBitmaps_Scenery.Add(new Bitmap(arrImageScenery[intImageCounter]));
                    }
                }

                float fltPCLevel = (float)Level / (float)classLevel.intNumMaxLevels;
                int intRetVal = (int)(fltPCLevel * lstBitmaps_Scenery.Count);
                return lstBitmaps_Scenery[intRetVal];
            }
        }

        static List<Bitmap> lstBitmaps_Airplanes = new List<Bitmap>();
        public static Bitmap bmpAirplane
        {
            get
            {
                if (lstBitmaps_Airplanes.Count == 0)
                {
                    string strDirectory = System.IO.Directory.GetCurrentDirectory() + "\\";

                    string[] arrImageAirplanes = System.IO.Directory.GetFiles(strDirectory, "airplane*.png");

                    for (int intImageCounter = 0; intImageCounter < arrImageAirplanes.Length; intImageCounter++)
                    {
                        Bitmap bmpAirplane_New = new Bitmap(arrImageAirplanes[intImageCounter]);
                        bmpAirplane_New.MakeTransparent(bmpAirplane_New.GetPixel(0, 0));
                        lstBitmaps_Airplanes.Add(bmpAirplane_New);
                    }
                }

                return lstBitmaps_Airplanes[(int)Airplane_Rank];
            }
        }

        public static Bitmap Banner_GetImage(classMathProblem cProblem)
        {
            return Banner_GetImage(0, cProblem);
        }

        static Bitmap bmpBanner = null;
        static Bitmap bmpBanner_Temp = null;

        public static Bitmap Banner_GetImage(float fltAngle, classMathProblem cProblem)
        {
            if (bmpBanner == null)
            {
                bmpBanner = (Bitmap)new Bitmap(Properties.Resources.banner);
                bmpBanner.MakeTransparent(bmpBanner.GetPixel(0, 0));
            }

            if (bmpBanner_Temp != null)
            {
                bmpBanner_Temp.Dispose();
            }

            bmpBanner_Temp = new Bitmap(bmpBanner);

            Point ptBannerTextCenter = new Point(58, 17);
            Point ptText = new Point(ptBannerTextCenter.X - cProblem.sz.Width / 2,
                                     ptBannerTextCenter.Y - cProblem.sz.Height / 2);
            using (Graphics g = Graphics.FromImage(bmpBanner_Temp))
            {
                g.DrawString(cProblem.strProblem, fntProblem, Brushes.Black, ptText);
            }

            bmpBanner_Temp = Math3.classGraphics.Rotate(bmpBanner_Temp, fltAngle);
            return bmpBanner_Temp;
        }

        public static enuAirplane_Rank Airplane_Rank
        {
            get
            {
                float fltPCLevel = (float)Level / (float)classLevel.intNumMaxLevels;
                int intRetVal = (int)(fltPCLevel * lstBitmaps_Airplanes.Count);
                return (enuAirplane_Rank)intRetVal;
            }
        }

        static Bitmap _bmpRingOfFire = null;
        static Bitmap bmpRingOfFire
        {
            get
            {
                if (_bmpRingOfFire == null)
                {
                    _bmpRingOfFire = new Bitmap(Properties.Resources.ring_of_fire);
                    _bmpRingOfFire.MakeTransparent(_bmpRingOfFire.GetPixel(0, 0));
                }
                return _bmpRingOfFire;
            }
        }

        float _fltLakeSceneAR = -1;
        float fltLakeSceneAR
        {
            get
            {
                if (_fltLakeSceneAR < 0)
                    _fltLakeSceneAR = (float)bmpScenery.Height * (float)bmpScenery.Width;

                return _fltLakeSceneAR;
            }
        }



        static Bitmap _bmpWorking = null;
        public static Bitmap bmpWorking
        {
            get
            {
                float fltARBmp = (float)bmpScenery.Height / (float)bmpScenery.Width;
                int intHeight = 1000;
                Size szBmpWorking = new Size((int)(intHeight / fltARBmp),
                                             intHeight);

                if (_bmpWorking != null)
                {
                    if (_bmpWorking.Width != szBmpWorking.Width || _bmpWorking.Height != szBmpWorking.Height)
                    {
                        _bmpWorking.Dispose();
                        _bmpWorking = null;
                    }
                }

                if (_bmpWorking == null)
                    _bmpWorking = new Bitmap(szBmpWorking.Width, szBmpWorking.Height);
                return _bmpWorking;
            }
        }


        static float fltTranslationFactor = 1.0f;

        static Bitmap _bmpOutput = null;
        public static Bitmap bmpOutput
        {
            get
            {
                if (_bmpOutput != null)
                {
                    if (_bmpOutput.Width != szBmpOutput.Width || _bmpOutput.Height != szBmpOutput.Height)
                    {
                        _bmpOutput.Dispose();
                        _bmpOutput = null;
                    }
                }

                if (_bmpOutput == null)
                    _bmpOutput = new Bitmap(szBmpOutput.Width, szBmpOutput.Height);

                fltTranslationFactor = (float)bmpWorking.Height / (float)_bmpOutput.Height;
                return _bmpOutput;
            }
        }


        static int _intHeight = Screen.PrimaryScreen.Bounds.Height - 45;
        public static int intHeight
        {
            get { return _intHeight; }  
            set
            {
                _intHeight = value;
            }
        }

        static Size _szBmpOutput = new Size(1, 1);
        static Size szBmpOutput
        {
            get
            {
                if (_szBmpOutput.Height != intHeight)
                {
                    float fltAR = 2f;
                    float fltHeight = (float)intHeight;
                    int intWidth = (int)(fltHeight / fltAR);
                    _szBmpOutput = new Size(intWidth, (int)fltHeight);
                }
                return _szBmpOutput;
            }
        }




        public static int ProblemDifficulty
        {
            get
            {
                int intReval = 1 + intScore / 50;
                if (intReval > 20)
                    intReval = 20;
                return intReval;

            }
        }





        public static int intScore = 0;
        public static int Score
        {
            get { return intScore; }
            set
            {
                intScore = value;


                if (lstProblems.Count == 0)
                {
                    //classMathProblem.Problem_LaunchNew();
                    classMathProblem.cEventTicket_NewProblem.Reschedule();
                }
            }
        }

        public static int intLevel = 0;
        public static int Level
        {
            get { return intLevel; }
            set
            {
                //if (intLevel != value)
                {
                    intLevel = value;
                    NumProblemsRemaining = cLevel.NumProblems;
                    NewLevelAnimation = true;
                }
            }
        }

        public static classLevel cLevel
        {
            get
            {
                return classLevel.cLevel_Current;
                //if (Level >= 0 && Level < classLevel.lstLevels.Count)
                //    return classLevel.lstLevels[Level];
                //else
                //    return classLevel.lstLevels[classLevel.lstLevels.Count - 1];
            }
        }

        public static int intNumProblemsRemaining = 0;
        public static int NumProblemsRemaining
        {
            get { return intNumProblemsRemaining; }
            set
            {
                if (intNumProblemsRemaining != value)
                {
                    intNumProblemsRemaining = value;
                }
            }
        }
        ContextMenu cmnu = new ContextMenu();

        RichTextBox rtxUI = new RichTextBox();

        public static classEventController cEC = new classEventController();
        static classEventController.classEventTicket cEventTicket_GamePlay = null;
        static classEventController.classEventTicket cEventTicket_NewLevelAnimation = null;
        //static classEventController.classEventTicket cEventTicket_Resize = null;
        static classEventController.classEventTicket cEventTicket_Grab = null;
        static classEventController.classEventTicket cEventTicket_TimePiece = null;

        static Random rnd = new Random();

        public static bool _bolFlash = true;
        public static bool bolFlash
        {
            get { return _bolFlash; }
            set 
            {
                _bolFlash = value; 
                if (!bolFlash)
                {
                    instance.Show();
                    instance.BringToFront();
                }
            }
        }
        static bool debug = false;

        
        public formBombingMath()
        {
            instance = this;
            InitializeComponent();
            ControlBox = false;

            string strDirTest = "C:\\Users\\chris\\OneDrive\\Bombing Math\\Bombing Math\\bin\\Debug";
            string strWorking = System.IO.Directory.GetCurrentDirectory();
            debug = strDirTest == strWorking;

            FormBorderStyle = FormBorderStyle.None;

            string strCurrentDir = System.IO.Directory.GetCurrentDirectory();

            _bolDeveloper = strCurrentDir == @"C:\C Sharp\Projects - Games\Bombing Math\Bombing Math\bin\Debug";

            Controls.Add(rtxUI);
            rtxUI.KeyDown += rtxUI_KeyDown;
            rtxUI.BringToFront();


            cEventTicket_GamePlay = cEC.Ticket("GamePlay", 100, tmrGamePlay_Tick);
            cEventTicket_GamePlay.quit();
            
            cEventTicket_NewLevelAnimation = cEC.Ticket("NewLevelAnimation", 4000, tmrNewLevelAnimation_Tick);
            cEventTicket_NewLevelAnimation.quit();

            //cEventTicket_Resize = cEC.Ticket("Resize", 100, tmrResize_Tick);
            //cEventTicket_Resize.quit();
            
            cEventTicket_Grab = cEC.Ticket("Grab", 100, tmrGrab_Tick);
            cEventTicket_Grab.quit();


            cEventTicket_TimePiece = cEC.Ticket("TimePice", 15000, tmrTimePiece_Tick);
            cEventTicket_TimePiece.quit();

            rtxUI.Focus();
            rtxUI.LostFocus += RtxUI_LostFocus;

            ContextMenu = cmnu;
            cmnu.Popup += Cmnu_Popup;

            Hide();


            MouseMove += FormBombingMath_MouseMove;
            MouseClick += FormBombingMath_MouseClick;
            MouseDown += FormBombingMath_MouseDown;
            MouseUp += FormBombingMath_MouseUp;
            MouseWheel += FormBombingMath_MouseWheel;
            SizeChanged += FormBombingMath_SizeChanged;
            FormClosing += FormBombingMath_FormClosing;
            Activated += FormBombingMath_Activated;
            VisibleChanged += FormBombingMath_VisibleChanged;
        }


        bool _bolTimePieceActive = false;
        public bool bolTimePieceActive
        {
            get { return _bolTimePieceActive; }
            set 
            {
                _bolTimePieceActive = value;
                cEventTicket_TimePiece.AutoRepeat = _bolTimePieceActive;
            }
        }

        void tmrTimePiece_Tick(object sender, EventArgs e)
        {
            bolTimePieceActive = false;
        }

        private void FormBombingMath_MouseWheel(object sender, MouseEventArgs e)
        {
            int intStepSize = 10;
            int intHeight_Min = 100;
            int intHeight_Max = Screen.PrimaryScreen.WorkingArea.Height;
            int intHeight_New = intHeight + (Math.Sign( e.Delta) * intStepSize);
            if (intHeight_New < intHeight_Min)
                intHeight_New = intHeight_Min;
            else if (intHeight_New > intHeight_Max)
                intHeight_New = intHeight_Max;
            intHeight = intHeight_New;
        }

        private void FormBombingMath_VisibleChanged(object sender, EventArgs e)
        {
            if (bolFlash)
            {
                Hide();
                return;
            }
            cEventTicket_GamePlay.AutoRepeat = Visible;

        }

        bool bolActivated = false;
        private void FormBombingMath_Activated(object sender, EventArgs e)
        {
            if (bolActivated) return;
            Visible = false;
            Hide();
            new formFlash();

            classPreferences.Load();

            if (Bottom > Screen.PrimaryScreen.WorkingArea.Height)
                Top = Screen.PrimaryScreen.WorkingArea.Height - Height;
                if (Top < 0) Top = 0;

            if (Left < 0)
                Left = 0;
            if (Right > Screen.PrimaryScreen.WorkingArea.Width)
                Left = Screen.PrimaryScreen.WorkingArea.Width - Width;
            
            Game_Resume();
            bolActivated = true;
        }

        private void FormBombingMath_MouseUp(object sender, MouseEventArgs e)
        {
            //cEventTicket_Resize.AutoRepeat = false;
            cEventTicket_Grab.AutoRepeat = false;
        }

        private void FormBombingMath_MouseDown(object sender, MouseEventArgs e)
        {
            //if (cEleUnderMouse == cSPEle_Resize)
            //{
            //    cEventTicket_Resize.AutoRepeat = true;
            //}
            //else
            if (cEleUnderMouse == cSPEle_Grab)
            {
                ptGrab = new Point(e.X, e.Y);
                cEventTicket_Grab.AutoRepeat = true;
            }

        }

        static bool _bolNewLevelAnimation = false;
        static public bool NewLevelAnimation
        {
            get { return _bolNewLevelAnimation; }
            set
            {
                //if (_bolNewLevelAnimation != value)
                {
                    _bolNewLevelAnimation = value;
                    if (_bolNewLevelAnimation)
                    {
                        cEventTicket_NewLevelAnimation.Reschedule();
                    }
                    else
                    {
                        classPreferences.SetCurrentValues();
                        classMathProblem.cEventTicket_LaunchBonus.Reschedule();
                    }
                }
            }
        }


        void tmrNewLevelAnimation_Tick(object sender, EventArgs e)
        {
            NewLevelAnimation = false;
        }
        void tmrGrab_Tick(object sender, EventArgs e)
        {
            Point ptMouse = MousePosition;
            //Point ptTL = PointToScreen(new Point());
            Location = new Point(ptMouse.X - ptGrab.X, ptMouse.Y - ptGrab.Y);

        }

        static Point ptGrab = new Point();


        //void tmrResize_Tick(object sender, EventArgs e)
        //{
        //    Point ptMouse = MousePosition;

        //    Point ptTL = PointToScreen(new Point());

        //    intHeight = ptMouse.Y - ptTL.Y;


        //}

        private void FormBombingMath_FormClosing(object sender, FormClosingEventArgs e)
        {
            classPreferences.Save();
        }

        private void Cmnu_Popup(object sender, EventArgs e)
        {
            cmnu.MenuItems.Clear();

            ContextMenu.MenuItems.Clear();
            MenuItem mnuGame_New = new MenuItem("new game");
            int intNumPerMenu = 25;
            for (int intLevel_MenuCounter = 1; intLevel_MenuCounter <= classPreferences.HighestLevelReached; intLevel_MenuCounter+=intNumPerMenu)
            {
                int intMax = intLevel_MenuCounter + intNumPerMenu;
                if (intMax > classPreferences.HighestLevelReached)
                    intMax = classPreferences.HighestLevelReached;
                MenuItem mnuGame_New_LevelList = new MenuItem("Levels (" + intLevel_MenuCounter.ToString() + "-" + intMax.ToString() + ")");

                for (int intLeveAllowedCounter = intLevel_MenuCounter; intLeveAllowedCounter < intMax; intLeveAllowedCounter++)
                {
                    MenuItem mnuGame_New_LevelAllowed = new MenuItem("Level:" + intLeveAllowedCounter.ToString(), mnuGame_New_Click);
                    mnuGame_New_LevelAllowed.Tag = (object)intLeveAllowedCounter;
                    mnuGame_New_LevelList.MenuItems.Add(mnuGame_New_LevelAllowed);
                }
                mnuGame_New.MenuItems.Add(mnuGame_New_LevelList);
            }

            ContextMenu.MenuItems.Add(mnuGame_New);

            MenuItem mnuQuit = new MenuItem("Quit", mnuQuit_Click);
            cmnu.MenuItems.Add(mnuQuit);
        }

        void mnuGame_New_Click(object sender, EventArgs e)
        {
            MenuItem mnuSender = (MenuItem)sender;
            try
            {
                int intLevelSelected = (int)mnuSender.Tag;

                Game_New(intLevelSelected);
            }
            catch (Exception)
            {

            }
        }

        void Game_Reset(int intLevel)
        {
            classLevel.classPreference_LevelUp cLevelUp = (intLevel >= 0 && intLevel < classLevel.lstLevelUp.Count)
                                                                  ? classLevel.lstLevelUp[intLevel]
                                                                  : new classLevel.classPreference_LevelUp();
            classLevel.cLevel_Current_Reset();
            for (int intToolCounter = 0; intToolCounter < arrTools_Inventory.Length; intToolCounter++)
            {
                arrTools_Inventory[intToolCounter] = cLevelUp.arrTools[intToolCounter];
            }
            Score = cLevelUp.Score;
            bolNewGame = true;
            cEventTicket_GamePlay.AutoRepeat = true;
            GameIsOver = false;
        }

        void mnuQuit_Click(object sender, EventArgs e)
        {
            Close();
        }
        
        void Game_New() { Game_New(1); }
        void Game_New(int intLevelStart)
        {
            lstExplosions.Clear();
            lstExponentialBombs.Clear();
            lstProblems.Clear();
            Game_Reset(intLevelStart);
            
            cEventTicket_NewLevelAnimation.quit();
            Level = intLevelStart;
            bolNewGame = true;
            classMathProblem.cEventTicket_NewProblem.AutoRepeat = true;
            cEventTicket_GamePlay.AutoRepeat = true;

            GameIsOver = false;
        }

        void Game_Resume()
        {
            bolNewGame = false;
            cEventTicket_NewLevelAnimation.quit();
            Level = classPreferences.LoadLevel;
            Score = classPreferences.LoadScore;
            classMathProblem.lstProblems.Clear();
            classMathProblem.lstProblems.AddRange(classPreferences.lstLoad_MathProblems);
            classFallingPrize.lst.Clear();
            classFallingPrize.lst.AddRange(classPreferences.lstLoad_FallingPrizes);
            classMathProblem.NumProblemsRemaining = classPreferences.intLoad_NumProblemsRemaining;
            cLevel.cBonusParameters.Count = classPreferences.intLoad_NumBonusParameterCount;
            ToolInventory_Resume();
            GameIsOver = false;

            classMathProblem.cEventTicket_NewProblem.AutoRepeat = true;
        }
        void ToolInventory_Resume()
        {
            formBombingMath.arrTools_Inventory[(int)enuTools.Bomb] = classPreferences.ToolCount_Bombs;
            formBombingMath.arrTools_Inventory[(int)enuTools.ExponentialBomb] = classPreferences.ToolCount_ExponentialBombs;
            formBombingMath.arrTools_Inventory[(int)enuTools.SpyGlass] = classPreferences.ToolCount_SpyGlass;
            formBombingMath.arrTools_Inventory[(int)enuTools.TimePiece] = classPreferences.ToolCount_TimePiece;
        }

        private void FormBombingMath_SizeChanged(object sender, EventArgs e)
        {

        }

        Point _ptMouseOutput = new Point();
        Point ptMouseOutput
        {
            get { return _ptMouseOutput; }
            set
            {
                _ptMouseOutput = value;
                cEleUnderMouse = cSP.Search(ptMouseWorking);
            }
        }

        Point ptMouseWorking
        {
            get
            {
                return ptTranslate_OutputToOutput(ptMouseOutput);
            }
        }


        classSweepAndPrune.classElement _cEleUnderMouse = null;
        classSweepAndPrune.classElement cEleUnderMouse
        {
            get { return _cEleUnderMouse; }
            set
            {
                if (_cEleUnderMouse != value)
                {
                    _cEleUnderMouse = value;
                    if (_cEleUnderMouse == null)
                    {
                        cProblemUnderMouse = null;
                    }
                    else
                    {
                        if (cEleUnderMouse.obj != null)
                        {
                            try
                            {
                                cProblemUnderMouse = (classMathProblem)cEleUnderMouse.obj;
                            }
                            catch (Exception)
                            {
                                ;
                            }
                        }
                    }
                }


                //if (cEleUnderMouse != null && cEleUnderMouse.tag != null)
                //{
                //    System.Diagnostics.Debug.Print((string)cEleUnderMouse.tag);
                //}
            }
        }


        Point ptTranslate_WorkingToOutput(Point ptWorking)
        {
            // fltFactor = working / output 
            Point ptRetVal = new Point((int)( ptWorking.X / fltTranslationFactor), 
                                       (int)(ptWorking.Y / fltTranslationFactor));
            return ptRetVal;
        }

        
        Point ptTranslate_OutputToOutput(Point ptMouseOutput)
        {
            // fltFactor = Output / output 
            Point ptRetVal = new Point((int)( ptMouseOutput.X * fltTranslationFactor), 
                                       (int)(ptMouseOutput.Y * fltTranslationFactor));
            return ptRetVal;
        }



        private void FormBombingMath_MouseClick(object sender, MouseEventArgs e)
        {
            if (cEleUnderMouse != null)
            {
                int intTool = lstSPEle_ToolButtons.IndexOf(cEleUnderMouse);
                if (intTool >= 0)
                {
                    enuTools eToolButton_UnderMouse = (enuTools)intTool;
                    switch (eToolButton_UnderMouse)
                    {
                        case enuTools.Bomb:
                            {
                                if (cProblemUnderMouse != null)
                                {
                                    rtxUI.Text = cProblemUnderMouse.Solution.ToString();
                                    arrTools_Inventory[intTool]--;
                                }
                            }
                            break;

                        case enuTools.ExponentialBomb:
                            {
                                classExponentialBomb cEBomb = new classExponentialBomb();
                                lstExponentialBombs.Add(cEBomb);
                                cEBomb.ptCenter = new Point(cProblemUnderMouse.cEle.rec.Left + cProblemUnderMouse.cEle.rec.Width / 2,
                                                            cProblemUnderMouse.cEle.rec.Top + cProblemUnderMouse.cEle.rec.Height / 2);
                                arrTools_Inventory[intTool]--;
                            }
                            break;

                        case enuTools.SpyGlass:
                            {
                                cProblemUnderMouse.ShowSolution = true;
                                arrTools_Inventory[intTool]--;
                            }
                            break;

                        case enuTools.TimePiece:
                            {
                                arrTools_Inventory[intTool]--;
                                bolTimePieceActive = true;
                            }
                            break;
                    }
                }
                //else if (cEleUnderMouse == cSPEle_Resize)
                //{
                //    cEventTicket_Resize.AutoRepeat = !cEventTicket_Resize.AutoRepeat;
                //}
            }
        }

        private void FormBombingMath_MouseMove(object sender, MouseEventArgs e)
        {
            ptMouseOutput = new Point(e.X, e.Y);
        }




        private void RtxUI_LostFocus(object sender, EventArgs e)
        {
            if (formCodeUpdateJournal.instance.Visible) return;
            rtxUI.Focus();
        }



        public static void ExplosionCreateNew(Point pt, int intNumStars)
        {
            for (int intStarCounter = 1; intStarCounter <= intNumStars; intStarCounter++)
            {
                enuStartype eStarType = (enuStartype)rnd.Next(classExplosion.StarTypeNum);

                lstExplosions.Add(new classExplosion(pt, eStarType));
            }
        }

        void Explosions_Move()
        {
            for (int intExplosionCounter = lstExplosions.Count - 1; intExplosionCounter >= 0; intExplosionCounter--)
            {
                classExplosion cExplosion = lstExplosions[intExplosionCounter];
                cExplosion.fltSize += 0.08f;
                if (cExplosion.fltSize >= 0.9)
                {
                    lstExplosions.Remove(cExplosion);
                }
                else
                {
                    //cExplosion.vel.X = (int)(cExplosion.vel.X * .9);
                    //cExplosion.vel.Y = (int)(cExplosion.vel.Y * .9);
                    cExplosion.pt.X += cExplosion.vel.X;
                    cExplosion.pt.Y += cExplosion.vel.Y;
                }
            }
        }

        void Problems_Move()
        {
            if (bolTimePieceActive) return;
            if (GameIsOver) return;

            try
            {
                IEnumerable<classMathProblem> query = lstProblems.OrderByDescending(problem => problem.pt.Y);
                classMathProblem.lstProblems = (List<classMathProblem>)query.ToList<classMathProblem>();
            }
            catch (Exception err)
            {

            }


            for (int intProblemCounter = lstProblems.Count - 1; intProblemCounter >= 0; intProblemCounter--)
            {
                classMathProblem cProblem = lstProblems[intProblemCounter];
                cProblem.pt.Y += cProblem.vel.Y;
                cProblem.pt.X += cProblem.vel.X;
                if (cProblem.IAmBonus)
                {
                    switch(cProblem.cBonus.eType)
                    {
                        case enuBonusQuizType.airplane:
                            {
                                if (cProblem.vel.X > 0)
                                {
                                    if (cProblem.cBonus.rec.Left > Width)
                                    {

                                        cProblem.die = true;
                                        goto quitProblem;
                                    }
                                }
                                else
                                {
                                    Size szAirplane = bmpAirplane.Size;
                                    if (cProblem.pt.X < szAirplane.Width)
                                    {
                                        cProblem.die = true;
                                        goto quitProblem;
                                    }
                                }
                            }
                            break;
                    }
                    
                }
                else
                {
                    cProblem.vel.X = (int)(cProblem.vel.X * .7);
                    if (cProblem.pt.X + cProblem.sz.Width > bmpWorking.Width)
                    {
                        if (cProblem.vel.X > 0)
                            cProblem.vel.X *= -1;
                        else
                            cProblem.pt.X = bmpWorking.Width - cProblem.sz.Width;
                    }
                    
                    if (cProblem.pt.X < 0)
                    {
                        if (cProblem.vel.X < 0)
                            cProblem.vel.X *= -1;
                        else
                            cProblem.pt.X = 0;
                    }
                }

                List<classSweepAndPrune.classElement> lstCollidingProblems = cSP.Search(cProblem.cEle.rec);
                for (int intCollidingPieceCounter = 0; intCollidingPieceCounter < lstCollidingProblems.Count; intCollidingPieceCounter++)
                {
                    classSweepAndPrune.classElement cEleColliding = lstCollidingProblems[intCollidingPieceCounter];
                    if (cEleColliding != cProblem.cEle)
                    {
                        if (cProblem.IAmBonus)
                        {
                            // move everything else up/down
                            if (cEleColliding.tag != null)
                            {
                                try
                                {
                                    classMathProblem cProblemColliding = (classMathProblem)cEleColliding.tag;

                                    if (!cProblemColliding.IAmBonus)
                                    {
                                        int intDistanceBetweenThem = (int)Math.Sqrt(Math.Pow(cProblem.pt.X - cProblemColliding.pt.X, 2) + Math.Pow(cProblem.pt.Y - cProblemColliding.pt.Y, 2));
                                        int intMaxDistance = cEleColliding.rec.Width + cProblem.cEle.rec.Width;
                                        int intVShift = intMaxDistance - intDistanceBetweenThem;
                                        if (intVShift < 0)
                                            intVShift = 0;
                                        if (cProblemColliding.pt.Y < cProblem.pt.Y)
                                            cProblemColliding.pt.Y -= intVShift / 2;
                                        else
                                            cProblemColliding.pt.Y += intVShift / 2;

                                        if (cProblem.vel.X < 0)
                                        {
                                            cProblemColliding.vel.X = intVShift / 4;
                                        }
                                        else
                                        {
                                            cProblemColliding.vel.X = intVShift / 4;
                                        }
                                    }
                                }
                                catch (Exception)
                                {

                                }
                            }
                        }
                        else
                        {   // move everything else left/right 
                            if (cEleColliding.tag != null)
                            {
                                try
                                {
                                    classMathProblem cProblemColliding = (classMathProblem)cEleColliding.tag;

                                    if (!cProblem.IAmBonus)
                                    {
                                        if (cProblemColliding.pt.X < cProblem.pt.X)
                                            cProblemColliding.pt.X--;
                                        else
                                            cProblemColliding.pt.X++;
                                    }
                                }
                                catch (Exception)
                                {

                                }
                            }
                        }
                    }
                }

            quitProblem:
                //if (cProblem.IAmBonus)
                //{
                //    cProblem.ShowSolution = true;
                //}

                if (cProblem.die)
                    lstProblems.Remove(cProblem);

                if (!cProblem.die && !cProblem.IAmBonus && cProblem.pt.Y > bmpWorking.Height - 10 - cProblem.sz.Height)
                {
                    GameOver();
                }

            }
        }

        static bool bolGameIsOver = false;
        public static bool GameIsOver
        {
            get { return bolGameIsOver; }
            set { bolGameIsOver = value; }  
        }


        void GameOver()
        {
            GameIsOver = true;
            // draw game over
            //cEventTicket_GamePlay.AutoRepeat = false;
            classMathProblem.cEventTicket_NewProblem.AutoRepeat = false;
        }


        void testValidSolution()
        {
            try
            {
                if (rtxUI.Text.Length > 0)
                {
                    int intPlayerAnser = (int)Convert.ToInt32(rtxUI.Text);
                    for (int intCounter = 0; intCounter < lstProblems.Count; intCounter++)
                    {
                        classMathProblem cProblem = lstProblems[intCounter];

                        if (!cProblem.Solved)
                        {
                            if (cProblem.Solution == intPlayerAnser)
                            {
                                cProblem.ProblemSolved(true);
                                rtxUI.Text = "";

                                if (cProblem.IAmBonus)
                                {
                                    //arrTools_Inventory[(int)cProblem.cBonus.eTool]++;
                                    new classFallingPrize(ref cProblem);
                                    cProblem.Kill();
                                }

                                break;
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {

            }

        }
        public static Font fntProblem = new Font("Ms sans-serif", 18);
        Font fntScore = new Font("courier", 14);
        Font fntLevel = new Font("courier", 18);
        Font fntNewLevel = new Font("ms sans-serif", 72);
        Font fntToolCount = new Font("courier", 12);
        Font fntUserInput = new Font("courier", 22);
        Font fntNumRemaining = new Font("courier", 12);
        
        void DrawScreen()
        {
            cSP.lstElements.Clear();
            
            Graphics g = Graphics.FromImage(bmpWorking);
            {
                Refresh();
                g.FillRectangle(Brushes.Red, new RectangleF(0, 0, bmpWorking.Width, bmpWorking.Height));
                recPlayingField.Size = new Size((int)(bmpWorking.Width * .9), bmpWorking.Height - rtxUI.Height);
                recPlayingField.Location = new Point((bmpWorking.Width - recPlayingField.Width) / 2, 0);

                recColumn = new Rectangle(0, 0, bmpWorking.Width - recPlayingField.Width, bmpWorking.Height);

                Rectangle recSource = new Rectangle(0, 0, bmpScenery.Width, bmpScenery.Height);
                Rectangle recDest = new Rectangle(0, 0, bmpWorking.Width, bmpWorking.Height);
                g.DrawImage(bmpScenery, recDest, recSource, GraphicsUnit.Pixel);

                DrawScreen_ToolLabels(ref g);
                //g.FillRectangle(Brushes.White, recColumn);
                DrawScreen_Explosions(ref g);
                DrawScreen_Score(ref g);
                DrawScreen_ExponentialBombs(ref g);
                DrawScreen_Level(ref g);
                DrawScreen_NumRemaining(ref g);
                DrawScreen_UserInput(ref g);
                if (DrawScreen_Problems(ref g))
                    DrawScreen_ToolButtons(ref g);
                classFallingPrize.DrawList(ref g);

                for (int intToolButtonCounter = 0; intToolButtonCounter < lstSPEle_ToolButtons.Count; intToolButtonCounter++)
                {
                    classSweepAndPrune.classElement cEleToolButton = lstSPEle_ToolButtons[intToolButtonCounter];
                    cEleToolButton.BringToFront();
                }


                if (NewLevelAnimation)
                {
                    DrawScreen_NewLevel(ref g);
                }


                DrawScreen_Grab(ref g);
                //DrawScreen_Resize(ref g);

                if (GameIsOver)
                    DrawScreen_GameOver(ref g);

            }
            g.Dispose();
            //bmpWorking.Save(@"c:\debug\bmpWorking.png");

            using (Graphics gOutput = Graphics.FromImage(bmpOutput))
            {
                Rectangle recSource = new Rectangle(0, 0, bmpWorking.Width, bmpWorking.Height);
                Rectangle recDest = new Rectangle(0, 0, bmpOutput.Width, bmpOutput.Height);
                gOutput.DrawImage(bmpWorking, recDest, recSource, GraphicsUnit.Pixel);
            }


                SetBitmap(bmpOutput);
        }


        void DrawScreen_Grab (ref Graphics g)
        {
            cSPEle_Grab.rec.Size = new Size(bmpWorking.Width, (int)(15*fltTranslationFactor));
            cSPEle_Grab.rec.Location = new Point(0,0);
            cSP.Add(ref cSPEle_Grab);
            cSPEle_Grab.tag = (object)"Grab";
            if (cEleUnderMouse == cSPEle_Grab)
            {
                g.FillRectangle(Brushes.White, cSPEle_Grab.rec);
                g.DrawRectangle(Pens.Black, cSPEle_Grab.rec);
            }
        }

        //void DrawScreen_Resize(ref  Graphics g)
        //{
        //    Size szREsize = new Size((int)(Width *.5),
        //                                      (int)(10 * fltTranslationFactor));
        //    if (szREsize.Height < 10)
        //        szREsize.Height = 10;
        //    cSPEle_Resize.rec.Size = szREsize;
        //    cSPEle_Resize.rec.Location = new Point((bmpWorking.Width - cSPEle_Resize.rec.Width)/2, 
        //                                           bmpWorking.Height - cSPEle_Resize.rec.Height);
        //    cSP.Add(ref cSPEle_Resize);
        //    cSPEle_Resize.tag = (object)"Resize";
        //    cSPEle_Resize.BringToFront();
        //    if (cEleUnderMouse == cSPEle_Resize)
        //    {
        //        g.FillRectangle(Brushes.White, cSPEle_Resize.rec);
        //        g.DrawRectangle(Pens.Black, cSPEle_Resize.rec);
        //    }
        //}

        void DrawScreen_NewLevel(ref Graphics g)
        {
            string strNewLevel = "Level " + Level.ToString();

            Size szNewLevel = TextRenderer.MeasureText(strNewLevel, fntNewLevel);
            Point ptNewLevel = new Point((bmpWorking.Width - szNewLevel.Width) / 2,
                                         (bmpWorking.Height - szNewLevel.Height) / 2);
            g.DrawString(strNewLevel, fntNewLevel, Brushes.Black, ptNewLevel);
            int intSpace = 5;
            g.DrawString(strNewLevel, fntNewLevel, Brushes.Yellow, new Point(ptNewLevel.X + intSpace, ptNewLevel.Y + intSpace));

        }

        void DrawScreen_UserInput(ref Graphics g)
        {
            string strUserInput = rtxUI.Text;
            Size szUserInput = TextRenderer.MeasureText(strUserInput, fntUserInput);
            int intGap = 2;
            Size szBoxUserInput = new Size(szUserInput.Width + intGap * 2,
                                       szUserInput.Height + intGap * 2);
            if (szBoxUserInput.Width < recColumn.Width)
                szBoxUserInput.Width = recColumn.Width;
            recUserInput = new Rectangle((bmpWorking.Width - szBoxUserInput.Width) / 2,
                                          bmpWorking.Height - szBoxUserInput.Height,
                                          szBoxUserInput.Width,
                                          szBoxUserInput.Height);
            g.FillRectangle(Brushes.Blue, recUserInput);
            g.DrawString(strUserInput, fntUserInput, Brushes.Yellow, new Point(recUserInput.Left + intGap, recUserInput.Top + intGap));
        }
        void DrawScreen_Level(ref Graphics g)
        {
            string strLevel = Level.ToString();
            Size szLevel = TextRenderer.MeasureText(strLevel, fntLevel);
            int intGap = 2;
            Size szBoxLevel = new Size(szLevel.Width + intGap * 2,
                                       szLevel.Height + intGap * 2);
            if (szBoxLevel.Width < recColumn.Width)
                szBoxLevel.Width = recColumn.Width;
            recLevel = new Rectangle(recScore.Left, recScore.Bottom, szBoxLevel.Width, szBoxLevel.Height);
            g.FillRectangle(Brushes.Blue, recLevel);
            g.DrawString(strLevel, fntLevel, Brushes.Yellow, new Point(recLevel.Left + intGap, recLevel.Top + intGap));
        }

        void DrawScreen_NumRemaining(ref Graphics g)
        {
            string strNumRemaining = NumProblemsRemaining.ToString();
            Size szNumRemaining = TextRenderer.MeasureText(strNumRemaining, fntNumRemaining);
            int intGap = 2;
            Size szBoxNumRemaining = new Size(szNumRemaining.Width + intGap * 2,
                                       szNumRemaining.Height + intGap * 2);
            if (szBoxNumRemaining.Width < recColumn.Width)
                szBoxNumRemaining.Width = recColumn.Width;
            recNumRemaining = new Rectangle(recScore.Left, recLevel.Bottom, szBoxNumRemaining.Width, szBoxNumRemaining.Height);
            g.FillRectangle(Brushes.Blue, recNumRemaining);
            g.DrawString(strNumRemaining, fntNumRemaining, Brushes.LightGray, new Point(recNumRemaining.Left + intGap, recNumRemaining.Top + intGap));
        }

        void DrawScreen_ExponentialBombs(ref Graphics g)
        {
            for (int intEBombCounter = 0; intEBombCounter < lstExponentialBombs.Count; intEBombCounter++)
            {
                classExponentialBomb cEBomb = lstExponentialBombs[intEBombCounter];
                Rectangle recSource = new Rectangle(0, 0, bmpRingOfFire.Width, bmpRingOfFire.Height);
                g.DrawImage(bmpRingOfFire, cEBomb.recDamage, recSource, GraphicsUnit.Pixel);
                //g.DrawEllipse(Pens.Red, cEBomb.recDamage);
            }
        }

        void DrawScreen_Score(ref Graphics g)
        {
            string strScore = Score.ToString();
            Size szScore = TextRenderer.MeasureText(strScore, fntScore);

            int intGap = 2;
            Size szBoxScore = new Size(szScore.Width + intGap * 2,
                                       szScore.Height + intGap * 2);
            if (szBoxScore.Width < recColumn.Width)
                szBoxScore.Width = recColumn.Width;
            recScore = new Rectangle(0, 0, szBoxScore.Width, szBoxScore.Height);
            g.FillRectangle(Brushes.Yellow, recScore);
            g.DrawString(Score.ToString(), fntScore, Brushes.Black, new Point(recScore.Left + intGap, recScore.Top + intGap));
        }

        Bitmap _bmpGameOver = null;
        Bitmap bmpGameOver
        {
            get
            {
                if (_bmpGameOver == null)
                {
                    string strGameOver = "Game Over";
                    Font fntGameOver = new Font("ms sans-serif", 34);
                    Size szGameOver = TextRenderer.MeasureText(strGameOver, fntGameOver);
                    _bmpGameOver = new Bitmap(szGameOver.Width, szGameOver.Height);
                    Color clrTransparent = Color.White;
                    using(Graphics g = Graphics.FromImage(_bmpGameOver))
                    {
                        g.FillRectangle(new SolidBrush(clrTransparent), new RectangleF(0, 0, _bmpGameOver.Width, _bmpGameOver.Height));
                        g.DrawString(strGameOver, fntGameOver, Brushes.Black, new Point());
                    }
                    _bmpGameOver.MakeTransparent(clrTransparent);
                }
                return _bmpGameOver;    
            }
        }

        int intGameOverBlink = 0;
        int intGameOverBlink_Grow = 50;
        void DrawScreen_GameOver(ref Graphics g)
        {
            
            Rectangle recSource = new Rectangle(new Point(), bmpGameOver.Size);
            intGameOverBlink += intGameOverBlink_Grow;
            if (intGameOverBlink > bmpOutput.Width)
                intGameOverBlink_Grow *= -1;
            else if (intGameOverBlink < 1)
                intGameOverBlink_Grow *= -1;
            //intGameOverBlink = 10;

            float fltAR = (float)bmpGameOver.Height / (float)bmpGameOver.Width;
            float fltOutput_Width = (float)intGameOverBlink;
            float fltOutput_Height = fltOutput_Width * fltAR;
            if (fltOutput_Width < 1)
                fltOutput_Width = 1;
            if (fltOutput_Height < 1)
                fltOutput_Height = 1;
            Size szOutput = new Size((int)fltOutput_Width, (int)fltOutput_Height);
            Point ptLocation = new Point((bmpOutput.Width - szOutput.Width)/2, (bmpOutput.Height - szOutput.Height)/2);
            Rectangle recDest = new Rectangle(ptLocation, szOutput);
            g.DrawImage(bmpGameOver, recDest, recSource, GraphicsUnit.Pixel);
        }

        classMathProblem _cProblemUnderMouse = null;
        classMathProblem cProblemUnderMouse
        {
            get { return _cProblemUnderMouse; }
            set { _cProblemUnderMouse = value; }
        }


        void DrawScreen_ToolButtons(ref Graphics g)
        {
            for (int intToolCounter = 0; intToolCounter < Tools_NumTypes; intToolCounter++)
            {
                enuTools eTool = (enuTools)intToolCounter;
                classSweepAndPrune.classElement cEleToolButton = lstSPEle_ToolButtons[intToolCounter];

                bool bolMouseOverButton = cEleUnderMouse == cEleToolButton;
                if (arrTools_Inventory[(int)eTool] > 0)
                {
                    g.FillRectangle(bolMouseOverButton ? Brushes.Yellow : Brushes.LightGray, cEleToolButton.rec);

                    Bitmap bmpTool = arrImages_Tools[(int)eTool];
                    Rectangle recSource = new Rectangle(0, 0, bmpTool.Width, bmpTool.Height);
                    bmpTool.MakeTransparent(bmpTool.GetPixel(0, 0));

                    g.DrawImage(bmpTool, cEleToolButton.rec, recSource, GraphicsUnit.Pixel);
                    g.DrawRectangle(Pens.Green, cEleToolButton.rec);

                    string strNum = "x" + arrTools_Inventory[intToolCounter].ToString();
                    Size szNum = TextRenderer.MeasureText(strNum, fntToolCount);
                    Point ptNum = new Point(cEleToolButton.rec.Right - szNum.Width, cEleToolButton.rec.Top);
                    g.DrawString(strNum, fntToolCount, Brushes.Black, ptNum);
                    g.DrawString(strNum, fntToolCount, Brushes.Black, new Point(ptNum.X - 1, ptNum.Y + 1));
                }
            }
        }
        bool DrawScreen_Problems(ref Graphics g)
        {
            bool bolRetVal = false;
            for (int intProblemCounter = 0; intProblemCounter < lstProblems.Count; intProblemCounter++)
            {
                classMathProblem cProblem = lstProblems[intProblemCounter];
                classSweepAndPrune.classElement cEleProblem = cProblem.cEle;
                cProblem.cEle.obj = (object)cProblem;

                if (cProblem.IAmBonus)
                {
                    Size szAirplane = bmpAirplane.Size;

                    cEleProblem.rec = new Rectangle(cProblem.pt, szAirplane);
                    cSP.Add(ref cEleProblem);
                    cEleProblem.obj = (object)cProblem;

                    g.DrawImage(bmpAirplane, cProblem.pt);
                    if (!cProblem.Solved)
                    {
                        enuAirplane_Rank eAirplaneRank = Airplane_Rank;
                        List<Point> lstBonusRecPoints = new List<Point>();
                        lstBonusRecPoints.Add(cProblem.pt);
                        lstBonusRecPoints.Add(new Point(cProblem.pt.X + bmpAirplane.Width, cProblem.pt.Y + bmpAirplane.Height));

                        switch (eAirplaneRank)
                        {
                            case enuAirplane_Rank.biWingAirplane:
                            case enuAirplane_Rank.airplane:
                            case enuAirplane_Rank.jet:
                                {
                                    float fltAngle = (float)Math.Atan((double)(-(float)cProblem.vel.Y / (float)cProblem.vel.X));

                                    Bitmap bmpBanner = Banner_GetImage(fltAngle, cProblem);

                                    g.DrawImage(bmpBanner, new Point(cProblem.pt.X - bmpBanner.Width,
                                                                     cProblem.pt.Y + bmpAirplane.Height / 2 - bmpBanner.Height / 2));

                                    lstBonusRecPoints.Add(new Point(cProblem.pt.X - bmpBanner.Width));
                                }
                                break;

                            default:
                                {
                                    Point ptAirplaneCenter = new Point(cProblem.pt.X + szAirplane.Width / 2,
                                                                       cProblem.pt.Y + szAirplane.Height / 2);
                                    Point ptProblem = new Point(ptAirplaneCenter.X - cProblem.sz.Width / 2,
                                                                ptAirplaneCenter.Y - cProblem.sz.Height / 2);
                                    Rectangle recBackground = new Rectangle();
                                    int intGap = 4;
                                    recBackground.X = ptProblem.X + intGap;
                                    recBackground.Y = ptProblem.Y + intGap;
                                    recBackground.Width = cProblem.sz.Width - 2 * intGap;
                                    recBackground.Height = cProblem.sz.Height - 2 * intGap;
                                    g.FillRectangle(Brushes.White, recBackground);
                                    g.DrawString(cProblem.strProblem, fntProblem, Brushes.White, ptProblem);
                                    g.DrawString(cProblem.strProblem, fntProblem, Brushes.Black, new Point(ptProblem.X + 1, ptProblem.Y + 1));
                                }
                                break;
                        }
                        cProblem.cBonus.rec = Math3.classMath3.RectangleThatContainsAllPoints(lstBonusRecPoints);

                    }
                }
                else
                {

                    if (cProblem.pt.X + cProblem.sz.Width > Width)
                        cProblem.pt.X = Width - cProblem.sz.Width;
                    cEleProblem.rec = new Rectangle(cProblem.pt, cProblem.sz);
                    cSP.Add(ref cEleProblem);
                    cEleProblem.obj = (object)cProblem;

                    if (cProblem.ShowSolution)
                    {
                        string strSolution = "=" + cProblem.Solution.ToString();
                        g.DrawString(strSolution, fntProblem, Brushes.Blue, cProblem.pt);
                        g.DrawString(strSolution, fntProblem, Brushes.Green, new Point(cProblem.pt.X + 1, cProblem.pt.Y + 1));
                    }
                    else
                    {
                        g.DrawString(cProblem.strProblem, fntProblem, Brushes.White, cProblem.pt);
                        g.DrawString(cProblem.strProblem, fntProblem, Brushes.Black, new Point(cProblem.pt.X + 1, cProblem.pt.Y + 1));
                    }

                    if (cProblemUnderMouse == cProblem)
                    {
                        // draw tool buttons 
                        Size szTool = new Size(24, 24);
                        Point ptBL = cEleProblem.rec.Location;
                        bolRetVal = true;
                        for (int intToolCounter = 0; intToolCounter < Tools_NumTypes; intToolCounter++)
                        {
                            enuTools eTool = (enuTools)intToolCounter;
                            classSweepAndPrune.classElement cEleToolButton = lstSPEle_ToolButtons[intToolCounter];
                            cEleToolButton.rec = new Rectangle(ptBL.X, ptBL.Y - szTool.Height, szTool.Width, szTool.Height);
                            cSP.Add(ref cEleToolButton);
                            ptBL.X = cEleToolButton.rec.Right;

                        }
                    }
                }

            quitProblem:
                ;
            }
            return bolRetVal;
        }

        public static Size szTool
        {
            get 
            {
                return new Size(recColumn.Width, recColumn.Width); 
            }
        }


        void DrawScreen_ToolLabels(ref Graphics g)
        {
        
            for (int intToolCounter = 0; intToolCounter < Tools_NumTypes; intToolCounter++)
            {
                enuTools eTool = (enuTools)intToolCounter;
                Rectangle recTool = new Rectangle(0, bmpWorking.Height - (intToolCounter + 1) * szTool.Height, szTool.Width, szTool.Height);

                bool bolMouseOver = cEleUnderMouse == lstSPEle_ToolButtons[intToolCounter];


                if (arrTools_Inventory[(int)eTool] > 0)
                {

                    g.FillRectangle(bolMouseOver ? Brushes.Yellow : Brushes.LightGray, recTool);
                    Bitmap bmpTool = arrImages_Tools[(int)eTool];
                    Rectangle recSource = new Rectangle(0, 0, bmpTool.Width, bmpTool.Height);
                    bmpTool.MakeTransparent(bmpTool.GetPixel(0, 0));
                    g.DrawImage(bmpTool, recTool, recSource, GraphicsUnit.Pixel);
                    g.DrawRectangle(Pens.Green, recTool);

                    string strNum = "x" + arrTools_Inventory[intToolCounter].ToString();
                    Size szNum = TextRenderer.MeasureText(strNum, fntToolCount);
                    Point ptNum = new Point(recTool.Right - szNum.Width, recTool.Top);
                    g.DrawString(strNum, fntToolCount, Brushes.Black, ptNum);
                    g.DrawString(strNum, fntToolCount, Brushes.Black, new Point(ptNum.X -1, ptNum.Y + 1));
                }
            }
        }

        void DrawScreen_Explosions(ref Graphics g)
        {
            Size szMaxStar = new Size(50, 50);
            for (int intExplosionCounter = 0; intExplosionCounter < lstExplosions.Count; intExplosionCounter++)
            {
                classExplosion cExplosion = lstExplosions[intExplosionCounter];
                float fltRndAngle = (float)(rnd.NextDouble() * 360);
                Bitmap bmpStarRotated = Math3.classGraphics.Rotate(cExplosion.bmpStar, fltRndAngle);
                bmpStarRotated.MakeTransparent(bmpStarRotated.GetPixel(0, 0));
                Rectangle recSourceStar = new Rectangle(0, 0, bmpStarRotated.Width, bmpStarRotated.Height);
                Size szDest = new Size((int)(szMaxStar.Width * cExplosion.fltSize),
                                       (int)(szMaxStar.Height * cExplosion.fltSize));
                int intMin = 5;
                if (szDest.Width < intMin)
                    szDest.Width = intMin;
                if (szDest.Height < intMin)
                    szDest.Height = intMin;
                Rectangle recDestStar = new Rectangle(cExplosion.pt.X - szDest.Width / 2,
                                                      cExplosion.pt.Y - szDest.Height / 2,
                                                      szDest.Width,
                                                      szDest.Height);
                g.DrawImage(bmpStarRotated, recDestStar, recSourceStar, GraphicsUnit.Pixel);
            }
        }
        static bool _bolNewGame = true;
        public static bool bolNewGame
        {
            get { return _bolNewGame; }
            set { _bolNewGame = value; }
        }

        void tmrGamePlay_Tick(object sender, EventArgs e)
        {
            if (formCodeUpdateJournal.instance.Visible)
                return;

            rtxUI.SendToBack();
            testValidSolution();
            Problems_Move();
            Explosions_Move();
            classFallingPrize.MoveList();
            DrawScreen();
        }

        private void rtxUI_KeyDown(object sender, KeyEventArgs e)
        {      
            switch (e.KeyCode)
            {
                case Keys.Back:
                case Keys.Delete:
                case Keys.Decimal:
                case Keys.Enter:
                    rtxUI.Text = "";
                    e.SuppressKeyPress = true;
                    break;

                case Keys.Escape:
                    {
                        if (debug)
                            formCodeUpdateJournal.ShowJournal();
                    }
                    break;

                case Keys.Home:
                    {
                        if (bolDeveloper)
                        {
                            if (!GameIsOver)
                            {
                                ///*
                                  classMathProblem.Problem_LaunchNew(true);
                               /*/
                                classMathProblem.NumProblemsRemaining = 1;
                                // */
                            }
                        }
                        e.SuppressKeyPress = true;
                    }
                    break;

                default:
                    {
                        Keys keyPressed = e.KeyCode;
                        bool bolValid = (keyPressed >= Keys.D0 && keyPressed <= Keys.D9)
                                    || (keyPressed >= Keys.NumPad0 && keyPressed <= Keys.NumPad9);
                        e.SuppressKeyPress = !bolValid;
                    }
                    break;
            }
        }
    }


    public class classExplosion
    {
        static Random rnd = new Random();
        public static int StarTypeNum
        {
            get
            {
                return Enum.GetNames(typeof(enuStartype)).Length;
            }
        }
        public Point pt = new Point();
        public Point vel = new Point();
        public float fltSize = 0.1f;
        public Bitmap bmpStar = null;
        public classExplosion(Point pt, enuStartype eType)
        {
            this.pt = pt;
            int intForce =10+ rnd.Next(30);
            vel = new Point(rnd.Next(intForce) - intForce / 2,
                             rnd.Next(intForce) - intForce / 2);

            //vel = new Point(5, 5);
            switch (eType)
            {
                case enuStartype.yellow:
                    bmpStar = (Bitmap)new Bitmap(Properties.Resources.star_yellow);
                    break;


                case enuStartype.green:
                    bmpStar = (Bitmap)new Bitmap(Properties.Resources.star_green);
                    break;


                case enuStartype.red:
                    bmpStar = (Bitmap)new Bitmap(Properties.Resources.star_red);
                    break;
            }
            bmpStar.MakeTransparent(bmpStar.GetPixel(0, 0));
        }

    }

}
