using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace TribbleExtinction
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : GenericGame
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        public World gameWorld;
        public Player myPlayer;
        public List<Enemy> enemies;
        public List<Effect> EffectList;
        public List<Node> NodeList;
        public EffectLibrary effectLibrary;
        public RandomGood rand;

        RedGun myRedGun;
        GreenGun myGreenGun;
        BlueGun myBlueGun;
        Texture2D firingTex1, firingTex2, flashTex;
        Vector2 firingTar;

        int nodeCount;
        int tileSize;
        public int enemyCount;
        int enemyMax;
        public int enemyRate;
        int enemyDead;

        Song music;
        SoundEffect groupDyingSound;

        float enemyProgress;
        Texture2D background;

        public Game1()
        {
            rand = new RandomGood();
            rand.pos = (System.DateTime.Now.Second + System.DateTime.Now.Minute * 60 + System.DateTime.Now.Hour*3600) % rand.count;
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        public override void Initialize()
        {
            Program.game = this;
            graphics = Program.masterGame.graphics;
            spriteBatch = Program.masterGame.spriteBatch;

            // TODO: Add your initialization logic here
            graphics.PreferredBackBufferWidth = 896;
            graphics.PreferredBackBufferHeight = 640;
            graphics.ApplyChanges();

            tileSize = 32;
            enemyMax = 500;
            nodeCount = 6;
            enemyCount = 50;
            enemyRate = 5;
            enemyDead = 0;

            gameWorld = new World(this, 896, 640, tileSize);
            myPlayer = new Player(this, tileSize);
            EffectList = new List<Effect>();
            effectLibrary = new EffectLibrary();
            enemies = new List<Enemy>();
            NodeList = new List<Node>();

            myRedGun = new RedGun(this);
            myGreenGun = new GreenGun(this);
            myBlueGun = new BlueGun(this, myPlayer.shipPosition);

            for (int i = 0; i < enemyCount; i++)
            {
                Enemy en = new Enemy(this, tileSize);

                en.pos = new Vector2(Program.game.rand.Next(100, 800), Program.game.rand.Next(100, 550));

                enemies.Add(en);
            }

            for (int i = 0; i < nodeCount; i++)
            {
                NodeList.Add(new Node());
            }

            firingTex1 = Program.masterGame.Content.Load<Texture2D>("crosshairs");
            firingTex2 = Program.masterGame.Content.Load<Texture2D>("crosshairs_blue");
            flashTex = Program.masterGame.Content.Load<Texture2D>("screen_flash");
            spriteBatch = new SpriteBatch(Program.masterGame.GraphicsDevice);


            music = Program.masterGame.Content.Load<Song>("CheerfulRhythmBGM");
            MediaPlayer.IsRepeating = true;
            MediaPlayer.Play(music);
            groupDyingSound = Program.masterGame.Content.Load<SoundEffect>("GroupSkugDeath");

            background = Program.masterGame.Content.Load<Texture2D>("background");
            Program.masterGame.IsMouseVisible = false;

            base.Initialize();
        }

        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public override void Update(GameTime gameTime)
        {
            enemyProgress += (float)gameTime.ElapsedGameTime.TotalSeconds;

            KeyboardState keybState = Keyboard.GetState();

            myPlayer.update(keybState, gameTime);
            
            for (int i = enemyCount-1; i >=0; i--)
            {
                if (enemies[i].poisoned) enemies[i].life = enemies[i].life - 4;
                if (enemies[i].life <= 0)
                {
                    int effected = 0;
                    for (int j = enemyCount - 1; j >= 0; j--)
                    {
                        if (Vector2.DistanceSquared(enemies[i].pos, enemies[j].pos) < 30 * 30)
                        {
                            effected++;
                            enemies[j].poisoned = true;
                            if (effected >= 4)
                                break;
                        }
                    }
                    effectLibrary.CreatePoisonSplat(enemies[i].pos);
                    enemies.RemoveAt(i);
                    enemyCount--;
                    //if (groupDyingSound.)
                    groupDyingSound.Play(0.2f, ((float)rand.NextDouble()  + 1f)/2f, 0f);
                    //groupDyingSound.Play(0.3f, 0.0f, 0.0f);
                }
                else
                    enemies[i].update(gameTime, myPlayer.dronePos);
            }

            for (int i = 0; i < nodeCount; i++)
            {
                NodeList[i].update(gameTime);
            }
            
            if (enemyProgress > 0.3)
            {
                enemyProgress -= 0.3f;
                if (enemyCount < enemyMax)
                {
                    for (int i = 0; i < enemyRate; i++)
                    {
                        enemies.Add(new Enemy(this, tileSize));
                    }
                    enemyCount += enemyRate;
                }
            }

            //Vector2 vec = new Vector2((float)rand.NextDouble() * 640, (float)rand.NextDouble() * 896);
            //effectLibrary.CreateRedBlob(vec);

            //Guns and projectiles
            MouseState cMouse = Mouse.GetState();
            myRedGun.update(cMouse, gameTime);
            myGreenGun.update(cMouse, gameTime);
            myBlueGun.update(cMouse, gameTime);
            firingTar = new Vector2(cMouse.X, cMouse.Y);

            base.Update(gameTime);
            if (myPlayer.DeathTimer < 2.5f)
                MediaPlayer.Stop();

            if (myPlayer.WinTimer < 0)
            {
                TitleGame tg = new TitleGame();
                tg.Background = Program.masterGame.Content.Load<Texture2D>("Win");
                tg.Initialize();
                Program.masterGame.ChildGame = tg;
            }
            if (myPlayer.DeathTimer < 0)
            {
                TitleGame tg = new TitleGame();
                tg.Background = Program.masterGame.Content.Load<Texture2D>("Lose");
                tg.Initialize();
                Program.masterGame.ChildGame = tg;
            }
        }

        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public override void Draw(GameTime gameTime)
        {
           
            Program.masterGame.GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin(SpriteSortMode.Immediate , BlendState.NonPremultiplied);

            //gameWorld.render(spriteBatch, gameTime);
            spriteBatch.Draw(background, new Rectangle(0, 0, 896, 640), Color.White);

            for (int i = 0; i < nodeCount; i++)
            {
                NodeList[i].render(spriteBatch, gameTime);
            }

            myPlayer.render(spriteBatch, gameTime);
            myRedGun.render(spriteBatch);
            myGreenGun.render(spriteBatch);
            myBlueGun.render(spriteBatch);

            for (int i = 0; i < enemyCount; i++)
            {
                enemies[i].render(spriteBatch);
            }
            for (int i = EffectList.Count - 1; i >= 0; i--)
            {
                //ef = EffectList[i];
                EffectList[i].render(spriteBatch, gameTime);
                if (EffectList[i].progress < 0)
                    EffectList.Remove(EffectList[i]);

            }

            if (Vector2.DistanceSquared(myPlayer.shipPosition, firingTar) < 100*100)
                spriteBatch.Draw(firingTex2, new Rectangle((int)firingTar.X - 25, (int)firingTar.Y - 25, 50, 50), Color.White);
            else
                spriteBatch.Draw(firingTex1, new Rectangle((int)firingTar.X-25, (int)firingTar.Y-25, 50, 50), Color.White);


            if (myPlayer.shipCorruptionCount > 20)
            {
                spriteBatch.Draw(flashTex, new Rectangle(0, 0, 896, 640), Color.White);
            }

            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}
