using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.GamerServices;

namespace MegaManRipoff.MainGameClasses
{
    /// <summary>
    /// Allows for items to be created. Designed to work with
    /// enemy and boss explosions.
    /// </summary>
    class ItemCreator
    {
        #region Member Variables

        /// <summary>
        /// The item creator's random number generator.
        /// </summary>
        static Random random;

        /// <summary>
        /// The maximum number used when generating a random number.
        /// </summary>
        const int Percentage = 100;

        /// <summary>
        /// Defines the probabilty, as a proportion of _perctange, of
        /// creating a small health capsule.
        /// </summary>
        static int _smallHealthThreshold;

        /// <summary>
        /// Defines the probabilty, as a proportion of _perctange, of
        /// creating a large health capsule.
        /// </summary>
        static int _largeHealthThreshold;

        /// <summary>
        /// Defines the probabilty, as a proportion of _perctange, of
        /// creating an extra life.
        /// </summary>
        static int _extraLifeThreshold;

        /// <summary>
        /// The velocity applied to created items to imply the effect
        /// of them "popping" out.
        /// </summary>
        const float PoppingSpeed = 6;

        #endregion

        #region Methods

        /// <summary>
        /// Initialises the probabilities of creating an item based on the difficulty.
        /// </summary>
        /// <param name="gameDifficulty">The game's difficulty.</param>
        public static void Initialise(GameDifficulty gameDifficulty)
        {
            switch (gameDifficulty)
            {
                case GameDifficulty.Easy:
                    _smallHealthThreshold = 30;
                    _largeHealthThreshold = 20;
                    _extraLifeThreshold = 5;
                    break;
                case GameDifficulty.Hard:
                    _smallHealthThreshold = 15;
                    _largeHealthThreshold = 5;
                    _extraLifeThreshold = 3;
                    break;
                default:
                    _smallHealthThreshold = 20;
                    _largeHealthThreshold = 10;
                    _extraLifeThreshold = 3;
                    break;
            }

            //Throw an exception if the thresholds add up to more than the
            //percentage.
            if (_smallHealthThreshold + _largeHealthThreshold > Percentage)
                throw new Exception("The given thresholds sum to more than the " +
                    "percentage value \"" + Percentage + "\".");

            //Create the random number generator.
            random = new Random();
        }

        /// <summary>
        /// Creates a small health capsule.
        /// </summary>
        /// <param name="room">The current room.</param>
        /// <param name="position">The centre position to create the item at.</param>
        private static void CreateSmallHealth(Room room, Vector2 position)
        {
            //Calculate the position to create the item (because its position
            //vector is at the top left of the sprite) and add it to the given room.
            Vector2 newPosition = new Vector2(position.X - 5,
                                              position.Y - 5);
            room.Add(new SmallHealth(room, newPosition, true, new Vector2(0, -PoppingSpeed)));
        }
        
        /// <summary>
        /// Creates a small health capsule.
        /// </summary>
        /// <param name="room">The current room.</param>
        /// <param name="position">The centre position to create the item at.</param>
        private static void CreateLargeHealth(Room room, Vector2 position)
        {
            //Calculate the position to create the item (because its position
            //vector is at the top left of the sprite) and add it to the given room.
            Vector2 newPosition = new Vector2(position.X - 8,
                                              position.Y - 8);
            room.Add(new LargeHealth(room, newPosition, true, new Vector2(0, -PoppingSpeed)));
        }

        /// <summary>
        /// Creates an extra life.
        /// </summary>
        /// <param name="room">The current room.</param>
        /// <param name="position">The centre position to create the item at.</param>
        private static void CreateExtraLife(Room room, Vector2 position)
        {
            //Calculate the position to create the item (because its position
            //vector is at the top left of the sprite) and add it to the given room.
            Vector2 newPosition = new Vector2(position.X - 8,
                                              position.Y - 8);
            room.Add(new ExtraLife(room, newPosition, true, new Vector2(0, -PoppingSpeed)));
        }

        /// <summary>
        /// Randomly creates an item at the given position.
        /// </summary>
        /// <param name="room">The current room.</param>
        /// <param name="position">The centre position to create the item at.</param>
        public static void CreateItem(Room room, Vector2 position)
        {
            //Generate a new random number.
            int result = random.Next(0, Percentage);

            //Create the relevant item.
            if (result < _smallHealthThreshold)
                CreateSmallHealth(room, position);
            else
                if (result < _largeHealthThreshold + _smallHealthThreshold)
                    CreateLargeHealth(room, position);
                else
                    if (result < _extraLifeThreshold + _largeHealthThreshold + _smallHealthThreshold)
                        CreateExtraLife(room, position);    
        }

        /// <summary>
        /// Creates an item at the given position.
        /// </summary>
        /// <param name="room">The current room.</param>
        /// <param name="position">The centre position to create the item at.</param>
        /// <param name="itemType">The item type to create.</param>
        public static void CreateItem(Room room, Vector2 position, Type itemType)
        {
            //Throw an exception if the given type is not an item or the given type is null.
            if (itemType == null || itemType.BaseType != typeof(Item))
                throw new ArgumentException("The given type " + itemType +
                    " does not inherit from Item.");

            //Otherwise, create the an item of the given type.
            if (itemType == typeof(SmallHealth))
                CreateSmallHealth(room, position);
            else
                if (itemType == typeof(LargeHealth))
                    CreateLargeHealth(room, position);
                else
                    if (itemType == typeof(ExtraLife))
                        CreateExtraLife(room, position);
        }

        #endregion
    }
}
