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

namespace MegaManRipoff.MainGameClasses
{
    /// <summary>
    /// Contains event data for when a boss health bar is created. 
    /// </summary>
    class NewBossHealthBarEventArgs : EventArgs
    {
        /// <summary>
        /// The boss introduction instance that created the new health bar.
        /// </summary>
        public BossIntroduction BossIntroduction { get; private set; }

        /// <summary>
        /// The boss instance.
        /// </summary>
        public IBoss Boss { get; private set; }

        public NewBossHealthBarEventArgs(BossIntroduction bossIntroduction, IBoss boss)
        {
            BossIntroduction = bossIntroduction;
            Boss = boss;
        }
    }

    /// <summary>
    /// The handle for the event called when a boss health bar is created.
    /// </summary>
    /// <param name="sender">The sender object.</param>
    /// <param name="e">Event arguments.</param>
    delegate void NewBossHealthBar(object sender, NewBossHealthBarEventArgs e);

    /// <summary>
    /// Displays relevant in-game information.
    /// </summary>
    class HeadsUpDisplay
    {
        #region Member Variables

        /// <summary>
        /// A reference to the current level.
        /// </summary>
        Level _level;

        /// <summary>
        /// The collection of components for the HUD.
        /// </summary>
        List<IHudComponent> _hudComponentsList; 

        #endregion

        /// <summary>
        /// The event called when a boss health bar is created.
        /// </summary>
        public event NewBossHealthBar OnNewBossHealthBar;

        public HeadsUpDisplay(Level level)
        {
            _level = level;
            _hudComponentsList = new List<IHudComponent>();
        }

        #region Methods

        /// <summary>
        /// Loads all assets associated with the HUD components.
        /// </summary>
        /// <param name="content">The game's content manager.</param>
        public static void LoadContent(ContentManager content)
        {
            HealthBar.LoadContent(content);
            TextDisplay.LoadContent(content);
            LivesCounter.LoadContent(content);
        }

        /// <summary>
        /// Creates a new health bar on the HUD.
        /// </summary>
        /// <param name="healthyEntity">Entity to display the health of.</param>
        /// <param name="position">The position of the health bar on the HUD.</param>
        /// <param name="colour">The colour of the health bar.</param>
        public void AddNormalHealthBar(HealthyEntity healthyEntity, Vector2 position, Color colour)
        {
            _hudComponentsList.Add(new HealthBar(healthyEntity, position, colour, HealthBar.Design.Normal));
        }

        /// <summary>
        /// Creates a new boss health bar on the HUD. This also causes the game to pause briefly
        /// and change to the boss music.
        /// </summary>
        /// <param name="bossIntroduction">The boss introduction instance that called this method.
        /// This is used so that the level knows when to unpause the game.</param>
        /// <param name="healthyEntity">Entity to display the health of.</param>
        /// <param name="position">The position of the health bar on the HUD.</param>
        /// <param name="colour">The colour of the health bar.</param>
        public void AddBossHealthBar(BossIntroduction bossIntroduction, HealthyEntity healthyEntity,
            Vector2 position, Color colour)
        {
            _hudComponentsList.Add(new HealthBar(healthyEntity, position, colour, HealthBar.Design.Boss));

            //Call the new boss health bar event so that the level can stop the game. Yes, I'm having
            //to access the level via the heads up display. See what I mean about awful??
            OnNewBossHealthBar(this, new NewBossHealthBarEventArgs(bossIntroduction, (IBoss)healthyEntity));
        }

        /// <summary>
        /// Removes a healthbar from the HUD, given the entity whose health 
        /// it is currently displaying.
        /// </summary>
        /// <param name="healthyEntity">The entity that the health bar is displaying
        /// the health of.</param>
        public void RemoveHealthBar(HealthyEntity healthyEntity)
        {
            bool found = false;
            int currentIndex = 0;

            //Iterate through the list and remove the first health bar whose
            //entity is the given entity.
            while (currentIndex < _hudComponentsList.Count && !found)
            {
                //Check if the current component is a health bar.
                if (_hudComponentsList[currentIndex] is HealthBar)
                {
                    //Cast the component as a health bar and check its Entity property.
                    HealthBar healthBar = (HealthBar)_hudComponentsList[currentIndex];
                    if (healthBar.HealthyEntity == healthyEntity)
                    {
                        _hudComponentsList.RemoveAt(currentIndex);
                        found = true;
                    }
                }

                currentIndex++;
            }

            //If the healthbar wasn't found, throw an exception.
            if (!found)
                throw new Exception("A matching health bar instance was not found.");
        }

        /// <summary>
        /// Adds text to the heads up display.
        /// </summary>
        /// <param name="text">The text to display.</param>
        /// <param name="position">The position of the text on the HUD.</param>
        public void AddText(string text, Vector2 position)
        {
            _hudComponentsList.Add(new TextDisplay(text, position));
        }

        /// <summary>
        /// Adds text to the heads up display.
        /// </summary>
        /// <param name="text">The text to display.</param>
        /// <param name="position">The position of the text on the HUD.</param>
        /// <param name="textColour">The colour of the text.</param>
        /// <param name="shadowColour">The colour of the text's shadow.</param>
        public void AddText(string text, Vector2 position, Color textColour, Color shadowColour)
        {
            _hudComponentsList.Add(new TextDisplay(text, position, textColour, shadowColour));
        }

        /// <summary>
        /// Adds a lives counter to the display.
        /// </summary>
        /// <param name="position">The position of the display on the HUD.</param>
        public void AddLivesCounter(Vector2 position)
        {
            _hudComponentsList.Add(new LivesCounter(position));
        }

        /// <summary>
        /// Draws the heads up display's components to the screen.
        /// </summary>
        /// <param name="spriteBatch">The sprite batch to draw to.</param>
        public void Draw(SpriteBatch spriteBatch)
        {
            foreach (IHudComponent hudComponent in _hudComponentsList)
            {
                hudComponent.Draw(spriteBatch);
            }
        }

        #endregion
    }
}
