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

namespace MegaManRipoff.MainGameClasses
{
    /// <summary>
    /// Handler for the event called when the boss introduction has finished.
    /// </summary>
    /// <param name="sender">The sender object.</param>
    /// <param name="e">Event arguments.</param>
    public delegate void BossIntroductionFinish(object sender, EventArgs e);

    /// <summary>
    /// Pauses the game briefly whilst the boss music starts playing
    /// and the boss' health bar fills up. This is probably the most
    /// fudgiest class ever. It completely breaks the rest of the implementation
    /// but oh well. Just please ignore this. It's horrible.
    /// </summary>
    class BossIntroduction
    {
        #region Member Variables

        /// <summary>
        /// The current room.
        /// </summary>
        Room _room;

        /// <summary>
        /// The boss instance this is associated with.
        /// </summary>
        HealthyEntity _boss;

        /// <summary>
        /// Holds the states of the boss introductions.
        /// </summary>
        enum State
        {
            WaitingForMusicFade, WaitingBeforeHealing, Healing
        }

        /// <summary>
        /// The current state of this boss introduction.
        /// </summary>
        State _currentState;

        /// <summary>
        /// Keeps track of how long to wait before healing is started.
        /// </summary>
        int _waitingBeforeHealingTimer;

        /// <summary>
        /// The length of time, in ticks, to wait before healing is started.
        /// </summary>
        const int WaitingBeforeHealingDuration = 60;

        /// <summary>
        /// Keeps track of how long to wait before incrementing the health and making
        /// the healing sound.
        /// </summary>
        int _healingGapTimer;

        /// <summary>
        /// The length of time, in ticks, between each health incrementation when the
        /// player is healing.
        /// </summary>
        const int HealingGapDuration = 4;

        /// <summary>
        /// Sound effect used when the boss is healing.
        /// </summary>
        static SoundEffect _healing;

        #endregion

        /// <summary>
        /// The event called when the boss introduction has finished.
        /// </summary>
        public event BossIntroductionFinish OnBossIntroductionFinish;

        /// <summary>
        /// Creates a new boss introduction.
        /// </summary>
        /// <param name="boss">The boss that is being introduced.</param>
        public BossIntroduction(Room room, HealthyEntity boss)
        {
            _room = room;
            _boss = boss;

            //Sets the boss' health to zero so we can heal it.
            _boss.Health = 0;

            //Create the boss' health bar and begin the chain of awful object orientation breaking
            //pieces of poopy code. Ughh.
            _room.HeadsUpDisplay.AddBossHealthBar(this, boss,
                new Vector2(_room.Camera.Area.Width - 21, 8), Color.White);
        }

        #region Methods

        /// <summary>
        /// Loads the assets required by the boss introductions.
        /// </summary>
        /// <param name="content">The game's content manager.</param>
        public static void LoadContent(ContentManager content)
        {
            _healing = content.Load<SoundEffect>("Sounds\\Healing");
        }

        /// <summary>
        /// Starts increasing the boss' health after a small delay.
        /// </summary>
        public void StartHealing()
        {
            //Wait for a short time before healing.
            _currentState = State.WaitingBeforeHealing;
            _waitingBeforeHealingTimer = WaitingBeforeHealingDuration;
        }

        /// <summary>
        /// Waits for a small period before changing to the healing state.
        /// </summary>
        private void WaitingBeforeHealing()
        {
            //Decrement the timer; if it is now zero, change to the healing state.
            if (--_waitingBeforeHealingTimer <= 0)
                _currentState = State.Healing;
        }

        /// <summary>
        /// Causes the boss's health to gradually increase and go "bee-dee-dee-dee...".
        /// </summary>
        private void Healing()
        {
            //Decrease the healing gap timer; if it is now zero, increase the health.
            if (--_healingGapTimer <= 0)
            {
                //If the player's health is equal to the target health value, stop healing.
                if (_boss.Health == _boss.MaxHealth)
                {
                    //Call the finished scrolling event.
                    OnBossIntroductionFinish(this, new EventArgs());
                }
                //Otherwise, keep healing.
                else
                {
                    //Increase the health and play the sound.
                    _boss.Health++;
                    _healing.Play();

                    //Reset the timer for the next loop.
                    _healingGapTimer = HealingGapDuration;
                }
            }
        }

        /// <summary>
        /// Updates the boss introduction.
        /// </summary>
        public void Update()
        {
            switch (_currentState)
            {
                case State.WaitingBeforeHealing:
                    WaitingBeforeHealing();
                    break;
                case State.Healing:
                    Healing();
                    break;
            }
        }

        #endregion
    }
}
