using Ck_Objects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Wordinator;
using System.Drawing;
namespace Bombing_Math
{
   

    public class classMathProblem
    {
        static int intIDCounter = 0;
        int intID = intIDCounter++;
        public int ID { get { return intID; } }

        #region StaticMethods_Vars_Properties
        public static List<classMathProblem> lstProblems = new List<classMathProblem>();

        public static classEventController cEC = formBombingMath.cEC;
        static Random rnd = new Random();

        public static int Level { get { return formBombingMath.Level; } }
        public static int MaxLevels { get { return classLevel.intNumMaxLevels; } }
        public static Bitmap bmpWorking { get { return formBombingMath.bmpWorking; } }  

        public static Font fntProblem { get { return formBombingMath.fntProblem; } }
        public static int ProblemDifficulty { get { return formBombingMath.ProblemDifficulty; } }
        public static int NumProblemsRemaining 
        {
            get { return formBombingMath.NumProblemsRemaining; } 
            set { formBombingMath.NumProblemsRemaining= value; } 
        }
        public static int Score 
        { 
            get { return formBombingMath.Score; } 
            set { formBombingMath.Score = value; } 
        }

        public static classLevel cLevel
        {
            get { return formBombingMath.cLevel; }
        }


        public static Rectangle recPlayingField { get { return formBombingMath.recPlayingField; } }
        static classEventController.classEventTicket _cEventTicket_NewProblem = null;
        static classEventController.classEventTicket _cEventTicket_LaunchBonus = null;
        public static classEventController.classEventTicket cEventTicket_NewProblem
        {
            get
            {
                if (_cEventTicket_NewProblem == null)
                {
                    _cEventTicket_NewProblem = cEC.Ticket("newproblem", 3000, tmrNewProblem_Tick);
                    _cEventTicket_NewProblem.AutoRepeat = true;
                }
                return _cEventTicket_NewProblem;
            }
        }
        public static classEventController.classEventTicket cEventTicket_LaunchBonus
        {
            get
            {
                if (_cEventTicket_LaunchBonus == null)
                {
                    _cEventTicket_LaunchBonus = cEC.Ticket("LaunchBonus", 1000, tmrLaunchBonus_Tick);
                    _cEventTicket_LaunchBonus.AutoRepeat = true;
                }
                return _cEventTicket_LaunchBonus;
            }
        }
        #endregion

        #region Bonus_Launch
        static public void tmrLaunchBonus_Tick(object sender, EventArgs e)
        {
            if (cLevel.cBonusParameters.Count > 0)
            {
                int intRnd = rnd.Next(0, NumProblemsRemaining >= 0 ? (NumProblemsRemaining * 2) : 0);
                if (intRnd <= cLevel.cBonusParameters.Count)
                {
                    Problem_LaunchNew(true);
                    cLevel.cBonusParameters.Count--;
                }
            }
            else
            {
                ;
            }
        }
        #endregion


        #region Problems_Launch
        static void tmrNewProblem_Tick(object sender, EventArgs e)
        {
            if (formCodeUpdateJournal.instance.Visible)
                return;
            Problem_LaunchNew();
        }

        public static void Problem_LaunchNew() { Problem_LaunchNew(false); }
        public static void Problem_LaunchNew(bool bolBonus)
        {
            if (formBombingMath.bolFlash) return;
            if (NumProblemsRemaining <= 0)
            {
                if (lstProblems.Count == 0)
                {
                    if (!formBombingMath.bolNewGame)
                        classLevel.LevelUp_Record();
                    formBombingMath.Level += 1;
                }

                if (!bolBonus) return;
            }

            if (formBombingMath.NewLevelAnimation) return;

            formBombingMath.bolNewGame = false;
                List<classLevel.classLevelProblemParameters> lstAllowedProblems = bolBonus 
                                                                                        ? cLevel.cBonusParameters.lstProblemTypesAllowed
                                                                                        : cLevel.lstProblemsAllowed;
            classLevel.classLevelProblemParameters cProblemAllowedRND = null;

            
                int intRnd = rnd.Next(lstAllowedProblems.Count);
                cProblemAllowedRND = lstAllowedProblems[intRnd];

            enuProblemTypes eProblemType = cProblemAllowedRND.eType;

            classMathProblem cProblemNew = null;
            switch (eProblemType)
            {
                case enuProblemTypes._plus_:
                    {
                        cProblemNew = Problem_LaunchNew__Plus_(cProblemAllowedRND);
                    }
                    break;

                case enuProblemTypes._minus_:
                    {
                        cProblemNew = Problem_LaunchNew__Minus_(cProblemAllowedRND);
                    }
                    break;

                case enuProblemTypes._multiply_:
                    {
                        cProblemNew = Problem_LaunchNew__Multiply_(cProblemAllowedRND);
                    }
                    break;

                case enuProblemTypes._divide_:
                    {
                        cProblemNew = Problem_LaunchNew__Divide_(cProblemAllowedRND);
                    }
                    break;

                case enuProblemTypes._multiply__plus_:
                    {
                        cProblemNew = Problem_LaunchNew__Multiply_plus(cProblemAllowedRND);
                    }
                    break;
                    
                case enuProblemTypes._multiply__minus_:
                    {
                        cProblemNew = Problem_LaunchNew__Multiply_minus(cProblemAllowedRND);
                    }
                    break;

                default:
                    {
                        cProblemNew = Problem_LaunchNew__Multiply_(cProblemAllowedRND);
                    }
                    break;
            }

            if (bolBonus)
            {
                switch(cLevel.cBonusParameters.eTypeAnimation)
                {
                    case enuBonusQuizType.airplane:
                        {
                            Size szAirplane = formBombingMath.bmpAirplane.Size;
                            enuAirplane_Rank eAirplaneRank = formBombingMath.Airplane_Rank;

                            switch (eAirplaneRank)
                            {
                                case enuAirplane_Rank.ballon:
                                    {
                                        cProblemNew.vel = new Point(2, -7);
                                        int intAltitude = bmpWorking.Height - szAirplane.Height;
                                        cProblemNew.pt = new Point(-szAirplane.Width, intAltitude);
                                    }
                                    break;
                                    
                                case enuAirplane_Rank.biWingAirplane:
                                    {
                                        cProblemNew.vel = new Point(5, 0);
                                        int intAltitude = rnd.Next(bmpWorking.Height / 10);
                                        cProblemNew.pt = new Point(-szAirplane.Width, intAltitude);
                                    }
                                    break;
                                    
                                case enuAirplane_Rank.airplane:
                                    {
                                        cProblemNew.vel = new Point(8, 0);
                                        int intAltitude = rnd.Next(bmpWorking.Height / 10);
                                        cProblemNew.pt = new Point(-szAirplane.Width, intAltitude);
                                    }
                                    break;
                                    
                                case enuAirplane_Rank.jet:
                                    {
                                        cProblemNew.vel = new Point(10, 3);
                                        int intAltitude = bmpWorking.Height /10 +  rnd.Next(bmpWorking.Height / 10);
                                        cProblemNew.pt = new Point(-szAirplane.Width, intAltitude);
                                    }
                                    break;
                                    
                                case enuAirplane_Rank.rocket:
                                    {
                                        cProblemNew.vel = new Point(8, -20);
                                        int intAltitude = bmpWorking.Height - szAirplane.Height;
                                        cProblemNew.pt = new Point(-szAirplane.Width, intAltitude);
                                    }
                                    break;
                                    
                                case enuAirplane_Rank.spaceship:
                                    {
                                        cProblemNew.vel = new Point(12, 0);
                                        int intAltitude = rnd.Next(bmpWorking.Height / 10);
                                        cProblemNew.pt = new Point(-szAirplane.Width, intAltitude);
                                    }
                                    break;


                            }

                            cProblemNew.cBonus = new classBonus();
                            cProblemNew.cBonus.eTool = cLevel.cBonusParameters.eToolsEarned;
                            cProblemNew.cBonus.eType = cLevel.cBonusParameters.eTypeAnimation;
                        }
                        break;
                }
            }
            else
            {
                int intFallingSpeed_Min = 1;
                int intFallingSpeed_Max = 2 + (int)(3 * (float)Level / (float)MaxLevels);
                cProblemNew.vel = new Point(0, intFallingSpeed_Min + rnd.Next(intFallingSpeed_Max - intFallingSpeed_Min));
            }

            lstProblems.Add(cProblemNew);
            NumProblemsRemaining -= 1;
            Problem_LaunchFrequency_Set();
        }

        static classMathProblem Problem_LaunchNew__Plus_(classLevel.classLevelProblemParameters cProblemParameters)
        {
            classMathProblem cRetVal = new classMathProblem();
            int intRange = cProblemParameters.Range_Max - cProblemParameters.Range_Min;

            if (intRange < 0)
                intRange = 10;
            int intRnd1 = cProblemParameters.Range_Min + rnd.Next(intRange);
            int intRnd2 = cProblemParameters.Range_Min + rnd.Next(intRange);

            cRetVal.Solution = intRnd1 + intRnd2;
            cRetVal.strProblem = intRnd1.ToString() + "+" + intRnd2.ToString();

            Size szProblem = TextRenderer.MeasureText(cRetVal.strProblem, fntProblem);


            int intRangeNext = recPlayingField.Width > 0
                                             ? recPlayingField.Width - szProblem.Width
                                             : (formBombingMath.bmpWorking != null
                                                                           ? formBombingMath.bmpWorking.Width - szProblem.Width
                                                                           : 10);
            


            cRetVal.pt = new Point(recPlayingField.Left + rnd.Next(intRangeNext), 0);


            return cRetVal;
        }

        static classMathProblem Problem_LaunchNew__Divide_(classLevel.classLevelProblemParameters cProblemParameters)
        {
            classMathProblem cRetVal = new classMathProblem();
            int intRange = cProblemParameters.Range_Max - cProblemParameters.Range_Min;

            if (intRange < 5)
                intRange = 5;
            int intRnd1 = cProblemParameters.Range_Min + rnd.Next(intRange);
            int intRnd2 = cProblemParameters.Range_Min + rnd.Next(intRange);

            int intProduct = intRnd1 * intRnd2;
            cRetVal.Solution = intRnd1;
            cRetVal.strProblem = intProduct.ToString() + "÷" + intRnd2.ToString();

            Size szProblem = TextRenderer.MeasureText(cRetVal.strProblem, fntProblem);
            cRetVal.pt = new Point(recPlayingField.Left + rnd.Next(recPlayingField.Width - szProblem.Width), 0);

      
            return cRetVal;
        }

        static classMathProblem Problem_LaunchNew__Minus_(classLevel.classLevelProblemParameters cProblemParameters)
        {
            classMathProblem cRetVal = new classMathProblem();
            int intRange = cProblemParameters.Range_Max - cProblemParameters.Range_Min;

            if (intRange < 0)
                intRange = 10;
            int intRnd1_Temp = cProblemParameters.Range_Min + rnd.Next(intRange);
            int intRnd2_Temp = cProblemParameters.Range_Min + rnd.Next(intRange);

            int intRnd1 = intRnd1_Temp > intRnd2_Temp ? intRnd1_Temp : intRnd2_Temp;
            int intRnd2 = intRnd1_Temp < intRnd2_Temp ? intRnd1_Temp : intRnd2_Temp;

            cRetVal.Solution = intRnd1 - intRnd2;
            cRetVal.strProblem = intRnd1.ToString() + "-" + intRnd2.ToString();

            Size szProblem = TextRenderer.MeasureText(cRetVal.strProblem, fntProblem);
            cRetVal.pt = new Point(recPlayingField.Left + rnd.Next(recPlayingField.Width - szProblem.Width), 0);

            return cRetVal;
        }

        static classMathProblem Problem_LaunchNew__Multiply_(classLevel.classLevelProblemParameters cProblemParameters)
        {
            classMathProblem cRetVal = new classMathProblem();
            int intRange = cProblemParameters.Range_Max - cProblemParameters.Range_Min;

            if (intRange < 5)
                intRange = 5;
            int intRnd1 = cProblemParameters.Range_Min + rnd.Next(intRange);
            int intRnd2 = cProblemParameters.Range_Min + rnd.Next(intRange);

            cRetVal.Solution = intRnd1 * intRnd2;
            cRetVal.strProblem = intRnd1.ToString() + "x" + intRnd2.ToString();

            Size szProblem = TextRenderer.MeasureText(cRetVal.strProblem, fntProblem);
            cRetVal.pt = new Point(recPlayingField.Left + rnd.Next(recPlayingField.Width - szProblem.Width), 0);

       
            return cRetVal;
        }
        
        static classMathProblem Problem_LaunchNew__Multiply_plus(classLevel.classLevelProblemParameters cProblemParameters)
        {
            classMathProblem cRetVal = new classMathProblem();
            int intRange = cProblemParameters.Range_Max - cProblemParameters.Range_Min;

            if (intRange < 5)
                intRange = 5;
            int intRnd1 = cProblemParameters.Range_Min + rnd.Next(intRange);
            int intRnd2 = cProblemParameters.Range_Min + rnd.Next(intRange);
            int intRnd3 = cProblemParameters.Range_Min + rnd.Next(intRange);

            cRetVal.Solution = intRnd1 * intRnd2 + intRnd3;
            cRetVal.strProblem = intRnd1.ToString() + "x" + intRnd2.ToString() + "+" + intRnd3;

            Size szProblem = TextRenderer.MeasureText(cRetVal.strProblem, fntProblem);
            cRetVal.pt = new Point(recPlayingField.Left + rnd.Next(recPlayingField.Width - szProblem.Width), 0);

      
            return cRetVal;
        }
                
        static classMathProblem Problem_LaunchNew__Multiply_minus(classLevel.classLevelProblemParameters cProblemParameters)
        {
            classMathProblem cRetVal = new classMathProblem();
            int intRange = cProblemParameters.Range_Max - cProblemParameters.Range_Min;

            if (intRange < 5)
                intRange = 5;
            int intRnd1, intRnd2, intRnd3;

            do
            {
                intRnd1 = cProblemParameters.Range_Min + rnd.Next(intRange);
                intRnd2 = cProblemParameters.Range_Min + rnd.Next(intRange);
                intRnd3 = cProblemParameters.Range_Min + rnd.Next(intRange);

                cRetVal.Solution = intRnd1 * intRnd2 - intRnd3;
            } while (cRetVal.Solution < 0);

            cRetVal.strProblem = intRnd1.ToString() + "x" + intRnd2.ToString() + "-" + intRnd3;

            Size szProblem = TextRenderer.MeasureText(cRetVal.strProblem, fntProblem);
            cRetVal.pt = new Point(recPlayingField.Left + rnd.Next(recPlayingField.Width - szProblem.Width), 0);

            return cRetVal;
        }

        static void Problem_LaunchFrequency_Set()
        {
            long lngDelay_Min = 3000 - 100 * ProblemDifficulty;
            if (lngDelay_Min < 1000)
                lngDelay_Min = 1000;
            long lngDelay_Max = 4000;
            long lngDelay_Range = lngDelay_Max - lngDelay_Min;

            cEventTicket_NewProblem.Milliseconds_ConditionTestDelay = lngDelay_Min + (long)rnd.Next((int)lngDelay_Range);
            cEventTicket_NewProblem.Reschedule();
        }
        #endregion


        public string strProblem = "";
        public int Solution = 0;
        public Point pt = new Point();
        public Point vel = new Point();
        public Size _sz = new Size();

        public Size sz
        {
            get
            {
                if (_sz.Width ==0)
                    _sz = TextRenderer.MeasureText(strProblem, fntProblem);

                return _sz;
            }
        }
        public classSweepAndPrune.classElement cEle = new classSweepAndPrune.classElement();
        classEventController.classEventTicket cEventTicket_ShowSolution_HideDelay = null;
        public classMathProblem()
        {
            cEventTicket_ShowSolution_HideDelay = cEC.Ticket("mathProblem(" + ID.ToString() + ")", 4000, tmrShowSolution_HideDelay_Tick);
            cEventTicket_ShowSolution_HideDelay.quit();
            cEle.tag = (object)this;
        }

        

        bool bolShowSolution = false;
        public bool ShowSolution
        {
            get { return bolShowSolution; }
            set
            {
                bolShowSolution = value;
                if (bolShowSolution)
                {
                    cEventTicket_ShowSolution_HideDelay.Reschedule();
                }
                else
                {
                    if (die)
                        lstProblems.Remove(this);
                }

            }
        }
        bool _boldie = false;
        public bool die
        {
            get { return _boldie; }
            set { _boldie = value; }
        }

        public void Kill()
        {
            die = true;
        }


        public bool Solved = false;
        public void ProblemSolved(bool bolExplosion)
        {
            if (cBonus == null)
            {
                die = true;
                ShowSolution = true;
            }
            
            Solved = true;
            
            Size szSolution = TextRenderer.MeasureText(strProblem, formBombingMath.fntProblem);
            formBombingMath.ExplosionCreateNew(new Point(pt.X + szSolution.Width / 2,
                                                         pt.Y + szSolution.Height / 2),
                                               bolExplosion ? 5 : 1);

            
            formBombingMath.Score += Solution.ToString().Length;
        }


        void tmrShowSolution_HideDelay_Tick(object sender, EventArgs e)
        {
            ShowSolution = false;
        }

        public classBonus cBonus = null;
        public bool IAmBonus
        {
            get { return cBonus != null; }
        }

        public class classBonus
        {
            enuTools _eTool = enuTools.SpyGlass;
            public enuTools eTool
            {
                get { return _eTool; }
                set { _eTool = value; }
            }
            public enuBonusQuizType eType = enuBonusQuizType.airplane;
            public Rectangle rec   = new Rectangle();
        }
    }

}
