using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Net;
using StrategicCombat.GameScreens;

namespace StrategicCombat
{
    /// <summary>
    /// This class represent the lobby for a local 2 player game.
    /// </summary>
    public class SinglePlayerLobby : GameScreen
    {
        #region Variables

        // Variables for the single human gamer.
        public SignedInGamer singleHumanGamer;
        public String singleHumanGamerTag;

        // Frame background texture.
        Texture2D frameBackgroundTexture;

        // Teams
        string[] teamStrings = { "USA", "Russia" };

        // Difficulty
        string[] difficultyStrings = { "Easy", "Medium", "Hard" };

        // Team textures.
        Texture2D teamZeroTexture;
        Texture2D teamOneTexture;

        // Xbox icons
        Texture2D aButtonTexture;
        Texture2D bButtonTexture;
        Texture2D xButtonTexture;
        Texture2D yButtonTexture;

        // Pc icons
        Texture2D enterButtonTexture;
        Texture2D escapeButtonTexture;
        Texture2D xKeyButtonTexture;
        Texture2D zKeyButtonTexture;

        // To draw Ready string and start game.
        public bool singlePlayerIsReady = false;

        // Constant x and y offsets
        const int xOffset = 128;
        const int yOffset = 72;

        #endregion

        #region Constructors

        /// <summary>
        /// Constructs a new lobby screen for a single player game.
        /// </summary>
        public SinglePlayerLobby(NetworkSession networkSession, PlayerIndex controllingPlayer)
        {

            // Get the signed in gamer
            this.singleHumanGamer = Gamer.SignedInGamers[controllingPlayer];
            this.singleHumanGamerTag = this.singleHumanGamer.Gamertag;
            
            TransitionOnTime = TimeSpan.FromSeconds(0.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);
        }


        /// <summary>
        /// Loads graphics content used by the lobby screen.
        /// </summary>
        public override void LoadContent()
        {
            // Create a new content manager.
            ContentManager content = ScreenManager.Game.Content;

            // Load background textures.
            this.frameBackgroundTexture = content.Load<Texture2D>("MenuAssets/white-background");
            this.teamZeroTexture = content.Load<Texture2D>("CombatUnits/LeftCombatUnits/LeftTank75");
            this.teamOneTexture = content.Load<Texture2D>("CombatUnits/RightCombatUnits/RightPlane75");

            // Load button textures
            this.aButtonTexture = content.Load<Texture2D>("MenuAssets/a");
            this.bButtonTexture = content.Load<Texture2D>("MenuAssets/b");
            this.xButtonTexture = content.Load<Texture2D>("MenuAssets/x");
            this.yButtonTexture = content.Load<Texture2D>("MenuAssets/y");
            this.enterButtonTexture = content.Load<Texture2D>("MenuAssets/enter");
            this.escapeButtonTexture = content.Load<Texture2D>("MenuAssets/escape");
            this.xKeyButtonTexture = content.Load<Texture2D>("MenuAssets/key_x");
            this.zKeyButtonTexture = content.Load<Texture2D>("MenuAssets/key_z");

        }

        #endregion

        #region Update

        /// <summary>
        /// Updates the lobby screen.
        /// </summary>
        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
                                                       bool coveredByOtherScreen)
        {
            base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);

            if (!IsExiting)
            {
                if (this.singlePlayerIsReady == true)
                {
                    LoadingScreen.Load(ScreenManager, true, this.singleHumanGamer.PlayerIndex, new GameplayScreen(null, 0));
                }
            }
        }

        /// <summary>
        /// Handles user input for all the local gamers in the session. Unlike most
        /// screens, which use the InputState class to combine input data from all
        /// gamepads, the lobby needs to individually mark specific players as ready,
        /// so it loops over all the local gamers and reads their inputs individually.
        /// </summary>
        public override void HandleInput(InputState input)
        {
            PlayerIndex playerIndex = this.singleHumanGamer.PlayerIndex;

            PlayerIndex unwantedOutput;

            if (input.IsMenuSelect(playerIndex, out unwantedOutput))
            {
                HandleMenuSelect(this.singleHumanGamer);
            }
            else if (input.IsMenuCancel(playerIndex, out unwantedOutput))
            {
                HandleMenuCancel(this.singleHumanGamer);
            }
            else if (input.IsMenuChangeTeam(playerIndex, out unwantedOutput))
            {
                HandleMenuChangeTeam(this.singleHumanGamer);
            }
            else if (input.IsMenuJoinGame(playerIndex, out unwantedOutput))
            {
                HandleMenuChangeDifficulty(this.singleHumanGamer);
            }

        } // End of the HandleInput method.


        /// <summary>
        /// Handle MenuSelect inputs by marking ourselves as ready.
        /// </summary>
        private void HandleMenuSelect(SignedInGamer gamer)
        {
            // Start the game.
            this.singlePlayerIsReady = true;
        }

        /// <summary>
        /// Handle MenuCancel inputs by clearing our ready status, or if it is
        /// already clear, prompting if the user wants to leave the session.
        /// </summary>
        private void HandleMenuCancel(SignedInGamer gamer)
        {
            MessageBoxScreen confirmQuitMessageBox = new MessageBoxScreen(Resources.ConfirmQuitGame);

            confirmQuitMessageBox.Accepted += ConfirmQuitMessageBoxAccepted;

            ScreenManager.AddScreen(confirmQuitMessageBox, ControllingPlayer);
        }

        /// <summary>
        /// Event handler for when the user selects ok on the "are you sure
        /// you want to quit" message box.
        /// </summary>
        private void ConfirmQuitMessageBoxAccepted(object sender, PlayerIndexEventArgs e)
        {

            LoadingScreen.Load(ScreenManager, false, null, new BackgroundScreen(), new MainMenuScreen());
        }

        /// <summary>
        /// Handle MenuChangeTeam inputs by changing team.
        /// </summary>
        private void HandleMenuChangeTeam(SignedInGamer gamer)
        {
            // Change the host team.
            Program.hostTeam = (byte)((Program.hostTeam + 1) % this.teamStrings.Length);
        }

        /// <summary>
        /// Handle MenuChangeDifficulty inputs by changing the difficulty.
        /// </summary>
        private void HandleMenuChangeDifficulty(SignedInGamer gamer)
        {
            // Change the difficulty level.
            if(Guide.IsTrialMode == false)
                Program.difficulty = (byte)((Program.difficulty + 1) % this.difficultyStrings.Length);
            else
                ScreenManager.AddScreen(new MessageBoxScreen(Resources.ErrorTrialMode), gamer.PlayerIndex);
        }

        #endregion

        #region Draw

        /// <summary>
        /// Draws the lobby screen.
        /// </summary>
        public override void Draw(GameTime gameTime)
        {
            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
            SpriteFont font = ScreenManager.Font;
            Texture2D frameTexture = ScreenManager.blankTexture;

            // Make the lobby slide into place during transitions.
            float transitionOffset = (float)Math.Pow(TransitionPosition, 2);

            spriteBatch.Begin();

            // The lobby title.
            string title = Resources.SinglePlayer;

            Vector2 titlePosition = new Vector2(xOffset, yOffset + 10);
            Vector2 titleOrigin = Vector2.Zero;
            Color titleColor = Color.White * TransitionAlpha;
            float titleScale = 2f;

            titlePosition.Y -= transitionOffset * 100;

            // Draw a rectangle for the game title
            spriteBatch.Draw(frameTexture, new Rectangle(0, yOffset, 1280, 68), Color.Orange * TransitionAlpha);

            // Dark shadow
            spriteBatch.DrawString(font, title, new Vector2(titlePosition.X + 1, titlePosition.Y + 1), Color.DarkGray * TransitionAlpha, 0,
                                   titleOrigin, titleScale, SpriteEffects.None, 0);

            // Title text
            spriteBatch.DrawString(font, title, titlePosition, titleColor, 0, titleOrigin, titleScale, SpriteEffects.None, 0);

            // Draw the first rectangle.
            spriteBatch.Draw(frameTexture, new Vector2(190, 160), new Rectangle(0, 0, 400, 400), Color.Black * TransitionAlpha, 0, Vector2.Zero, 1, SpriteEffects.None, 0);
            spriteBatch.Draw(frameBackgroundTexture, new Vector2(192, 162), new Rectangle(0, 0, 396, 396), Color.White * TransitionAlpha, 0, Vector2.Zero, 1, SpriteEffects.None, 0f);
            spriteBatch.DrawString(font, this.singleHumanGamerTag, new Vector2(196, 166), Color.DarkGray* TransitionAlpha, 0, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
            spriteBatch.DrawString(font, this.singleHumanGamerTag, new Vector2(194, 164), Color.Yellow * TransitionAlpha, 0, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
            
            if (Program.hostTeam == 0)
            {
                spriteBatch.DrawString(font, this.teamStrings[0], new Vector2(392, 272), Color.DarkGray * TransitionAlpha, 0, new Vector2(font.MeasureString(this.teamStrings[0]).X / 2, 0), 2f, SpriteEffects.None, 0);
                spriteBatch.DrawString(font, this.teamStrings[0], new Vector2(390, 270), Color.Blue * TransitionAlpha, 0, new Vector2(font.MeasureString(this.teamStrings[0]).X / 2, 0), 2f, SpriteEffects.None, 0);
                spriteBatch.Draw(this.teamZeroTexture, new Vector2(390, 380), new Rectangle(0, 0, 75, 75), Color.White * TransitionAlpha, 0, new Vector2(37.5f, 37.5f), 1.5f, SpriteEffects.None, 0);
            }
            else if (Program.hostTeam == 1)
            {
                spriteBatch.DrawString(font, this.teamStrings[1], new Vector2(392, 272), Color.DarkGray * TransitionAlpha, 0, new Vector2(font.MeasureString(this.teamStrings[1]).X / 2, 0), 2f, SpriteEffects.None, 0);
                spriteBatch.DrawString(font, this.teamStrings[1], new Vector2(390, 270), Color.Red * TransitionAlpha, 0, new Vector2(font.MeasureString(this.teamStrings[1]).X / 2, 0), 2f, SpriteEffects.None, 0);
                spriteBatch.Draw(this.teamOneTexture, new Vector2(390, 380), new Rectangle(0, 0, 75, 75), Color.White * TransitionAlpha, 0, new Vector2(37.5f, 37.5f), 1.5f, SpriteEffects.None, 0);
            }

            if (this.singlePlayerIsReady == true)
            {
                spriteBatch.DrawString(font, "Ready", new Vector2(392, 472), Color.DarkOrange * TransitionAlpha, 0, new Vector2(font.MeasureString("Ready").X / 2, 0), 2f, SpriteEffects.None, 0);
                spriteBatch.DrawString(font, "Ready", new Vector2(390, 470), Color.Yellow * TransitionAlpha, 0, new Vector2(font.MeasureString("Ready").X / 2, 0), 2f, SpriteEffects.None, 0);
            }

            // Draw the second rectangle.
            spriteBatch.Draw(frameTexture, new Vector2(690, 160), new Rectangle(0, 0, 400, 400), Color.Black * TransitionAlpha, 0, Vector2.Zero, 1, SpriteEffects.None, 0);
            spriteBatch.Draw(frameBackgroundTexture, new Vector2(692, 162), new Rectangle(0, 0, 396, 396), Color.White * TransitionAlpha, 0, Vector2.Zero, 1, SpriteEffects.None, 0);
            spriteBatch.DrawString(font, "Computer AI (" + this.difficultyStrings[Program.difficulty] + ")" , new Vector2(696, 166), Color.DarkGray* TransitionAlpha, 0, Vector2.Zero, 1.5f, SpriteEffects.None, 0);
            spriteBatch.DrawString(font, "Computer AI (" + this.difficultyStrings[Program.difficulty] + ")", new Vector2(694, 164), Color.Yellow * TransitionAlpha, 0, Vector2.Zero, 1.5f, SpriteEffects.None, 0);

            if (Program.hostTeam == 1)
            {
                spriteBatch.DrawString(font, this.teamStrings[0], new Vector2(892, 272), Color.DarkGray * TransitionAlpha, 0, new Vector2(font.MeasureString(this.teamStrings[0]).X / 2, 0), 2f, SpriteEffects.None, 0);
                spriteBatch.DrawString(font, this.teamStrings[0], new Vector2(890, 270), Color.Blue * TransitionAlpha, 0, new Vector2(font.MeasureString(this.teamStrings[0]).X / 2, 0), 2f, SpriteEffects.None, 0);
                spriteBatch.Draw(this.teamZeroTexture, new Vector2(890, 380), new Rectangle(0, 0, 75, 75), Color.White * TransitionAlpha, 0, new Vector2(37.5f, 37.5f), 1.5f, SpriteEffects.None, 0);
            }
            else if (Program.hostTeam == 0)
            {
                spriteBatch.DrawString(font, this.teamStrings[1], new Vector2(892, 272), Color.DarkGray * TransitionAlpha, 0, new Vector2(font.MeasureString(this.teamStrings[1]).X / 2, 0), 2f, SpriteEffects.None, 0);
                spriteBatch.DrawString(font, this.teamStrings[1], new Vector2(890, 270), Color.Red * TransitionAlpha, 0, new Vector2(font.MeasureString(this.teamStrings[1]).X / 2, 0), 2f, SpriteEffects.None, 0);
                spriteBatch.Draw(this.teamOneTexture, new Vector2(890, 380), new Rectangle(0, 0, 75, 75), Color.White * TransitionAlpha, 0, new Vector2(37.5f, 37.5f), 1.5f, SpriteEffects.None, 0);
            }

            spriteBatch.DrawString(font, "Ready", new Vector2(892, 472), Color.DarkOrange * TransitionAlpha, 0, new Vector2(font.MeasureString("Ready").X / 2, 0), 2f, SpriteEffects.None, 0);
            spriteBatch.DrawString(font, "Ready", new Vector2(890, 470), Color.Yellow * TransitionAlpha, 0, new Vector2(font.MeasureString("Ready").X / 2, 0), 2f, SpriteEffects.None, 0);

            // Draw a rectangle for buttons and keys
            spriteBatch.Draw(frameTexture, new Rectangle(0, 598, 1280, 48), Color.Orange * TransitionAlpha);

            // Button panel
            float buttonTextScale = 1.25f;
            String selectText = "Ready";
            String backText = "Leave game/Not ready";
            String changeTeamText = "Change team";
            String changeDifficultyText = "Change difficulty";
            float selectStringSize = xOffset + 32 + 40 + (font.MeasureString(selectText).X * buttonTextScale) + 5;
            float backStringSize = selectStringSize + 32 + 40 + (font.MeasureString(backText).X * buttonTextScale) + 5;
            float changeTeamSize = backStringSize + 32 + 40 + (font.MeasureString(changeTeamText).X * buttonTextScale) + 5;

#if (!XBOX360)

            // Draw select key with text (enter button)
            spriteBatch.Draw(enterButtonTexture, new Vector2(xOffset, 720 - yOffset - 42), Color.White * TransitionAlpha);

            spriteBatch.DrawString(font, selectText, new Vector2(xOffset + 41, 720 - yOffset - 40), Color.DarkGray * TransitionAlpha, 0,
                                   Vector2.Zero, buttonTextScale, SpriteEffects.None, 0);
            spriteBatch.DrawString(font, selectText, new Vector2(xOffset + 40, 720 - yOffset - 41), Color.White * TransitionAlpha, 0,
                                   Vector2.Zero, buttonTextScale, SpriteEffects.None, 0);

            // Draw back button with text (esc button)
            spriteBatch.Draw(escapeButtonTexture, new Vector2(selectStringSize, 720 - yOffset - 42), Color.White * TransitionAlpha);

            spriteBatch.DrawString(font, backText, new Vector2(selectStringSize + 41, 720 - yOffset - 40), Color.DarkGray * TransitionAlpha, 0,
                                   Vector2.Zero, buttonTextScale, SpriteEffects.None, 0);
            spriteBatch.DrawString(font, backText, new Vector2(selectStringSize + 40, 720 - yOffset - 41), Color.White * TransitionAlpha, 0,
                                   Vector2.Zero, buttonTextScale, SpriteEffects.None, 0);

            // Draw change team button with text (z button)
            spriteBatch.Draw(zKeyButtonTexture, new Vector2(backStringSize, 720 - yOffset - 42), Color.White * TransitionAlpha);

            spriteBatch.DrawString(font, changeTeamText, new Vector2(backStringSize + 41, 720 - yOffset - 40), Color.DarkGray * TransitionAlpha, 0,
                                   Vector2.Zero, buttonTextScale, SpriteEffects.None, 0);
            spriteBatch.DrawString(font, changeTeamText, new Vector2(backStringSize + 40, 720 - yOffset - 41), Color.White * TransitionAlpha, 0,
                                   Vector2.Zero, buttonTextScale, SpriteEffects.None, 0);

            // Draw change difficulty button with text (x button)
            spriteBatch.Draw(xKeyButtonTexture, new Vector2(changeTeamSize, 720 - yOffset - 42), Color.White * TransitionAlpha);

            spriteBatch.DrawString(font, changeDifficultyText, new Vector2(changeTeamSize + 41, 720 - yOffset - 40), Color.DarkGray * TransitionAlpha, 0,
                                   Vector2.Zero, buttonTextScale, SpriteEffects.None, 0);
            spriteBatch.DrawString(font, changeDifficultyText, new Vector2(changeTeamSize + 40, 720 - yOffset - 41), Color.White * TransitionAlpha, 0,
                                   Vector2.Zero, buttonTextScale, SpriteEffects.None, 0);

#endif

#if (XBOX360)

                // Draw select key with text (a button)
            spriteBatch.Draw(aButtonTexture, new Vector2(xOffset, 720 - yOffset - 42), Color.White * TransitionAlpha);

            spriteBatch.DrawString(font, selectText, new Vector2(xOffset + 41, 720 - yOffset - 40), Color.DarkGray * TransitionAlpha, 0,
                                   Vector2.Zero, buttonTextScale, SpriteEffects.None, 0);
            spriteBatch.DrawString(font, selectText, new Vector2(xOffset + 40, 720 - yOffset - 41), Color.White * TransitionAlpha, 0,
                                   Vector2.Zero, buttonTextScale, SpriteEffects.None, 0);

            // Draw back button with text (b button)
            spriteBatch.Draw(bButtonTexture, new Vector2(selectStringSize, 720 - yOffset - 42), Color.White * TransitionAlpha);

            spriteBatch.DrawString(font, backText, new Vector2(selectStringSize + 41, 720 - yOffset - 40), Color.DarkGray * TransitionAlpha, 0,
                                   Vector2.Zero, buttonTextScale, SpriteEffects.None, 0);
            spriteBatch.DrawString(font, backText, new Vector2(selectStringSize + 40, 720 - yOffset - 41), Color.White * TransitionAlpha, 0,
                                   Vector2.Zero, buttonTextScale, SpriteEffects.None, 0);

            // Draw change team button with text (y button)
            spriteBatch.Draw(yButtonTexture, new Vector2(backStringSize, 720 - yOffset - 42), Color.White * TransitionAlpha);

            spriteBatch.DrawString(font, changeTeamText, new Vector2(backStringSize + 41, 720 - yOffset - 40), Color.DarkGray * TransitionAlpha, 0,
                                   Vector2.Zero, buttonTextScale, SpriteEffects.None, 0);
            spriteBatch.DrawString(font, changeTeamText, new Vector2(backStringSize + 40, 720 - yOffset - 41), Color.White * TransitionAlpha, 0,
                                   Vector2.Zero, buttonTextScale, SpriteEffects.None, 0);

            // Draw change difficulty button with text (x button)
            spriteBatch.Draw(xButtonTexture, new Vector2(changeTeamSize, 720 - yOffset - 42), Color.White * TransitionAlpha);

            spriteBatch.DrawString(font, changeDifficultyText, new Vector2(changeTeamSize + 41, 720 - yOffset - 40), Color.DarkGray * TransitionAlpha, 0,
                                   Vector2.Zero, buttonTextScale, SpriteEffects.None, 0);
            spriteBatch.DrawString(font, changeDifficultyText, new Vector2(changeTeamSize + 40, 720 - yOffset - 41), Color.White * TransitionAlpha, 0,
                                   Vector2.Zero, buttonTextScale, SpriteEffects.None, 0);

#endif

            spriteBatch.End();

        } // End of the Draw method.

        #endregion

    } // End of class

} // End of namespace
