using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Media;
using MegaManRipoff.UI;

namespace MegaManRipoff.YouWinClasses
{
    /// <summary>
    /// Handles the winning screen.
    /// </summary>
    class YouWinScreen : GameState
    {
        #region Member Variables

        /// <summary>
        /// The game's difficulty setting, used so that the main game can be
        /// resumed on the same difficulty.
        /// </summary>
        GameDifficulty _gameDifficulty;

        /// <summary>
        /// The camera used for displaying the title screen nicely.
        /// </summary>
        Camera _camera;

        /// <summary>
        /// The text used for the header.
        /// </summary>
        readonly string _headerText = "You Win!!";

        /// <summary>
        /// The font used for the game over text.
        /// </summary>
        SpriteFont _headerFont;

        /// <summary>
        /// The victory jingle.
        /// </summary>
        Song _music;

        /// <summary>
        /// Whether or not the jingle has played.
        /// </summary>
        bool _hasPlayed;

        /// <summary>
        /// The texture used for the you win screen.
        /// </summary>
        Texture2D _youWinTexture;

        /// <summary>
        /// The text used for the disclaimer.
        /// </summary>
        readonly string _disclaimerText = "Well done, you got the cake!! Your quest for\n" +
                                          "adventure and your fight for everlasting peace\n" +
                                          "has been concluded by this incredibly elegant\n" +
                                          "kill screen!! Now go home and enjoy your dessert!!\n\n" +
                                          "No, the second level is not finished. There would\n" +
                                          "be more to the game but I ran out of time </3\n" +
                                          "Thanks for playing!!";

        /// <summary>
        /// The font used for the menu and disclaimer.
        /// </summary>
        SpriteFont _menuFont;

        /// <summary>
        /// The texture used for the cursor.
        /// </summary>
        Texture2D _cursorTexture;

        /// <summary>
        /// The offset of the cursor from the selected menu item.
        /// </summary>
        readonly Vector2 _cursorOffset = new Vector2(-28, 9);

        /// <summary>
        /// The game over menu.
        /// </summary>
        Menu _menu;

        /// <summary>
        /// The menu's items, used to subscribe and unsubscribe to/from their selection events.
        /// </summary>
        MenuItem _quitItem;

        #endregion

        /// <summary>
        /// The event called when the game over screen quits.
        /// </summary>
        public override event GameStateQuit OnGameStateQuit;

        /// <summary>
        /// Creates a new victory screen.
        /// </summary>
        /// <param name="game1">The current game.</param>
        /// <param name="gameDifficulty">The game's difficulty setting, used so
        /// that the main game can be resumed on the same difficulty.</param>
        public YouWinScreen(Game1 game1, GameDifficulty gameDifficulty)
            : base(game1)
        {
            _gameDifficulty = gameDifficulty;

            _hasPlayed = false;
        }

        #region Methods

        /// <summary>
        /// Initialises the game over screen.
        /// </summary>
        public override void Initialise()
        {
            //Create the camera.
            _camera = new Camera(_game1.GraphicsDevice, Vector2.Zero);
        }

        /// <summary>
        /// Loads the assets required by the game over screen.
        /// </summary>
        /// <param name="content">The game's content manager.</param>
        public override void LoadContent(ContentManager content)
        {
            _music = content.Load<Song>("Music\\Victory");

            _youWinTexture = content.Load<Texture2D>("Images\\GameOver");
            _cursorTexture = content.Load<Texture2D>("Images\\Cursor");

            _headerFont = content.Load<SpriteFont>("Fonts\\SegoeUI");
            _menuFont = content.Load<SpriteFont>("Fonts\\SegoeUISmall");
            _menuFont.LineSpacing = 22;

            Menu.LoadContent(content);

            //Create the menu. This is a pretty stupid place to do it, yes,
            //but it throws an exception anywhere else. Whatever.
            CreateMenu();
        }

        /// <summary>
        /// Plays the victory music once.
        /// </summary>
        private void PlayMusic()
        {
            //This ensures the music only plays once.
            if (!_hasPlayed && Game1.MUSIC)
            {
                MediaPlayer.IsRepeating = false;
                MediaPlayer.Play(_music);
                _hasPlayed = true;
            }
        }

        /// <summary>
        /// Creates the victory menu.
        /// </summary>
        private void CreateMenu()
        {
            _menu = new Menu(_menuFont, _cursorTexture, _cursorOffset, false);

            _quitItem = new MenuItem(_menu,
                                     "Press Start/Enter to \nreturn to the Title Screen",
                                     new Vector2(_camera.Area.Center.X - (_menuFont.MeasureString("Press Start/Enter to \nreturn to the Title Screen").X / 2),
                                                 230),
                                     70);
            _quitItem.OnSelected += new Selected(_quitItem_OnSelected);
            _menu.AddItem(_quitItem);
        }

        /// <summary>
        /// Updates the victory screen.
        /// </summary>
        /// <param name="gameTime"></param>
        public override void Update(GameTime gameTime)
        {
            //Play the jingle.
            PlayMusic();

            //Update the input handler.
            InputHelper.Update();

            //Update the camera (used for scaling).
            _camera.Update();

            //Update the menu.
            _menu.Update(gameTime);
        }

        /// <summary>
        /// Draws the header and disclaimer to the screen.
        /// </summary>
        private void DrawText(SpriteBatch spriteBatch)
        {
            //Position the string at the centre of the screen.
            Vector2 position = new Vector2(_camera.Area.Center.X - (_headerFont.MeasureString(_headerText).X / 2),
                                           16);

            //Draw the shadow, then the actual text.
            spriteBatch.DrawString(_headerFont,
                                   _headerText,
                                   position + Vector2.One,
                                   Color.Black);
            spriteBatch.DrawString(_headerFont,
                                   _headerText,
                                   position,
                                   Color.White);

            //Draw the shadow, then the actual text.
            spriteBatch.DrawString(_menuFont,
                                   _disclaimerText,
                                   new Vector2(50, 45) + Vector2.One,
                                   Color.Black);
            spriteBatch.DrawString(_menuFont,
                                   _disclaimerText,
                                   new Vector2(50, 45),
                                   Color.White);
        }

        /// <summary>
        /// Draws the game over screen to the screen.
        /// </summary>
        /// <param name="spriteBatch">The sprite batch to draw to.</param>
        public override void Draw(SpriteBatch spriteBatch)
        {
            //Start the sprite batch.
            spriteBatch.Begin(SpriteSortMode.Deferred,
                              BlendState.AlphaBlend,
                              SamplerState.PointWrap,
                              null, null, null,
                              _camera.ScaleTransformation);

            //Draw the background texture.
            spriteBatch.Draw(_youWinTexture, Vector2.Zero, Color.White);

            //Draw the text and menu.
            DrawText(spriteBatch);
            _menu.Draw(spriteBatch);

            spriteBatch.End();
        }

        #endregion

        #region Event Handles

        /// <summary>
        /// Method called when the quit item is selected.
        /// </summary>
        /// <param name="sender">The menu item that was selected.</param>
        /// <param name="e">Event arguments.</param>
        void _quitItem_OnSelected(object sender, EventArgs e)
        {
            //Go to the title screen, if there is a subscriber for the game state quit event.
            if (OnGameStateQuit != null)
                OnGameStateQuit(this, new GameStateQuitEventArgs(Game1.State.TitleScreen, _gameDifficulty));
        }

        #endregion
    }
}
