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

namespace MegaManRipoff.MainGameClasses
{
    /// <summary>
    /// The egg that the Pipi bird drops. Once this egg hits the floor,
    /// it will create many Pipi babies.
    /// </summary>
    class PipiEgg : Enemy
    {
        #region Member Variables

        /// <summary>
        /// The texture for Pipi eggs.
        /// </summary>
        static Texture2D _texture;

        /// <summary>
        /// The Pipi egg's maximum health.
        /// </summary>
        static int _maxHealth;

        /// <summary>
        /// The amount of damage Pipi eggs deal.
        /// </summary>
        static int _damage;

        /// <summary>
        /// The Pipi egg's animation.
        /// </summary>
        Animation _animation;

        /// <summary>
        /// The number of Pipi babies to create when this egg breaks.
        /// </summary>
        static int _numberOfBabies;

        /// <summary>
        /// A random number generator.
        /// </summary>
        Random _random;

        #endregion

        #region Properites

        /// <summary>
        /// Gets the amount of damage Pipi eggs do.
        /// </summary>
        public override int Damage
        {
            get { return _damage; }
        }

        /// <summary>
        /// The Pipi egg's hitbox.
        /// </summary>
        public override Rectangle Hitbox
        {
            get { return new Rectangle((int)_position.X - 17, (int)_position.Y - 16, 32, 31); }
        }

        #endregion

        /// <summary>
        /// Creates a new Pipi egg.
        /// </summary>
        /// <param name="room">The current room.</param>
        /// <param name="position">The position to create the Pipi egg.</param>
        /// <param name="direction">The direction of the Pipi egg.</param>
        public PipiEgg(Room room, Vector2 position, Direction direction)
            : base(room, position)
        {
            _direction = direction;

            _health = _maxHealth;
            _random = new Random();
        }

        #region Methods

        /// <summary>
        /// Initialises fields for the Pipi egg, dependent on the game's difficulty.
        /// </summary>
        /// <param name="gameDifficulty">The game's difficulty setting.</param>
        new public static void Initialise(GameDifficulty gameDifficulty)
        {
            switch (gameDifficulty)
            {
                case GameDifficulty.Easy:
                    _numberOfBabies = 3;
                    break;
                case GameDifficulty.Hard:
                    _numberOfBabies = 5;
                    break;
                default:
                    _numberOfBabies = 4;
                    break;
            }
            _maxHealth = 2;
            _damage = 5;
        }

        /// <summary>
        /// Initialises the animation for the Pipi egg.
        /// </summary>
        protected override void InitialiseAnimations()
        {
            //The only frame.
            _animation = new Animation(new Tuple<Rectangle, Vector2, int>(
                new Rectangle(0, 0, 32, 32), new Vector2(-17, -14), 0), 0);
        }

        /// <summary>
        /// Loads the assets for the Pipi egg.
        /// </summary>
        /// <param name="content">The game's content manager.</param>
        new public static void LoadContent(ContentManager content)
        {
            _texture = content.Load<Texture2D>("Images\\PipiEgg");
        }

        /// <summary>
        /// Causes the egg to break and release the Pipi babies. Not as
        /// interesting a method as the name may imply.
        /// </summary>
        private void MakeBabies()
        {
            //Make the babies.
            for (int i = 1; i <= _numberOfBabies; i++)
            {
                int direction = _random.Next(200, 340);

                _room.Add(new PipiBaby(_room,
                                       new Vector2(Hitbox.Center.X, Hitbox.Center.Y),
                                       EntityHelper.RadialToVector((float)_random.NextDouble() * 4, direction),
                                       _random.Next(0, 30)));
            }

            //Make the eggshells and explosion effects.
            _room.Add(new ExplosionEffect(_room, new Vector2(Hitbox.Center.X, Hitbox.Center.Y)));
            _room.Add(new Eggshell(_room, new Vector2(Hitbox.Left, Hitbox.Top), Eggshell.Half.Left));
            _room.Add(new Eggshell(_room, new Vector2(Hitbox.Center.X, Hitbox.Top), Eggshell.Half.Right));

            _room.Remove(this);
        }

        /// <summary>
        /// Updates the Pipi egg.
        /// </summary>
        /// <param name="gameTime">The current snapshot of time.</param>
        public override void Update(GameTime gameTime)
        {
            //Move according to gravity.
            _speed = EntityHelper.InduceGravity(_speed);
            _position += _speed;

            //If there is a collision with a tile, make babies.
            if (EntityHelper.CheckForSolidTiles(_room, Hitbox) != null)
                MakeBabies();

            base.Update(gameTime);
        }

        /// <summary>
        /// Draws the Pipi egg to the screen.
        /// </summary>
        /// <param name="spriteBatch">The sprite batch to draw to.</param>
        public override void Draw(SpriteBatch spriteBatch)
        {
            //Account for post-hit invincibility flashing.
            if ((_invincibiltyTimer / 2) % 2 == 0)
            {
                //Flip the sprite as needed.
                SpriteEffects directionEffects;

                if (_direction == Direction.Left)
                    directionEffects = SpriteEffects.None;
                else
                    directionEffects = SpriteEffects.FlipHorizontally;

                //Get the necessary details from the current animation frame.
                Rectangle currentFrameSource = _animation.CurrentFrame.Item1;
                Vector2 currentFrameOffset = _animation.CurrentFrame.Item2;

                spriteBatch.Draw(_texture,
                                 _position + currentFrameOffset,
                                 currentFrameSource,
                                 Color.White,
                                 0,
                                 Vector2.Zero,
                                 1,
                                 directionEffects,
                                 0);
            }
        }

        #endregion
    }
}
