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
{
    /// <summary>
    /// Holds the event arguments for when the main game ends.
    /// </summary>
    public class GameStateQuitEventArgs : EventArgs
    {
        /// <summary>
        /// The next game state after this one has ended.
        /// </summary>
        public Game1.State NextGameState { get; private set; }

        /// <summary>
        /// The game's current difficulty setting.
        /// </summary>
        public GameDifficulty GameDifficulty { get; private set; }

        /// <summary>
        /// The zero-based index of the level to be played. This is only considered if
        /// the next game state is Game1.State.MainGame.
        /// </summary>
        public int MainGameLevel { get; private set; }

        /// <summary>
        /// A constant that is used to say that the main game should start on the most
        /// recently played level.
        /// </summary>
        public const int MostRecentLevel = -1;

        /// <summary>
        /// Creates event data for when the main game ends. 
        /// </summary>
        /// <param name="nextGameState">The game's next state once the main game has quit.</param>
        /// <param name="gameDifficulty">The game's current difficulty setting.</param>
        public GameStateQuitEventArgs(Game1.State nextGameState, GameDifficulty gameDifficulty)
        {
            NextGameState = nextGameState;
            GameDifficulty = gameDifficulty;
            MainGameLevel = MostRecentLevel;
        }

        /// <summary>
        /// Creates event data for when the main game ends. 
        /// </summary>
        /// <param name="nextGameState">The game's next state once the main game has quit.</param>
        /// <param name="gameDifficulty">The game's current difficulty setting.</param>
        /// <param name="mainGameLevel">The zero-based index of the level to be played. This is only
        /// considered if the next game state is Game1.State.MainGame.</param>
        public GameStateQuitEventArgs(Game1.State nextGameState, GameDifficulty gameDifficulty, int mainGameLevel)
        {
            NextGameState = nextGameState;
            GameDifficulty = gameDifficulty;
            MainGameLevel = mainGameLevel;
        }
    }

    /// <summary>
    /// The handler for the event called when a game state ends.
    /// </summary>
    /// <param name="sender">The sender object.</param>
    /// <param name="e">The event arugments, if any.</param>
    public delegate void GameStateQuit(object sender, GameStateQuitEventArgs e);

    /// <summary>
    /// The base class for all other game states within the game.
    /// </summary>
    abstract class GameState
    {
        /// <summary>
        /// The current game.
        /// </summary>
        protected Game1 _game1;

        /// <summary>
        /// When overriden in an inheriting class, the event called when the game
        /// state quits.
        /// </summary>
        public abstract event GameStateQuit OnGameStateQuit;

        /// <summary>
        /// Creates a new game state instance.
        /// </summary>
        /// <param name="game1">The current game.</param>
        protected GameState(Game1 game1)
        {
            _game1 = game1;
        }

        #region Methods

        /// <summary>
        /// When overriden in an inheriting class, initialises the game state.
        /// </summary>
        public abstract void Initialise();

        /// <summary>
        /// When overriden in an inheriting class, loads the assets required by
        /// the game state.
        /// </summary>
        public abstract void LoadContent(ContentManager content);

        /// <summary>
        /// When overriden in an inheriting class, updates the game state.
        /// </summary>
        /// <param name="gameTime">The current snapshot of time.</param>
        public abstract void Update(GameTime gameTime);

        /// <summary>
        /// When overriden in an inheriting class, draws the game state.
        /// </summary>
        /// <param name="spriteBatch">The sprite batch to draw to.</param>
        public abstract void Draw(SpriteBatch spriteBatch);

        #endregion
    }
}
