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

namespace FredriksdalAssault2
{
    /// <summary>
    /// This class represents the logic for a deathmatch.
    /// </summary>
    public class DeathMatchModeLogic : GameModeLogic
    {

        #region Instance variables

        public String winningPlayer = "All players";
        public int totalNumberOfKills;
        public int maxKills = 0;
        public int latencyTime = 5000;

        #endregion

        #region Constructors

        /// <summary>
        /// Create new logic for a deathmatch.
        /// </summary>
        /// <param name="networkSession"></param>
        /// <param name="content"></param>
        /// <param name="graphicsDevice"></param>
        /// <param name="spriteBatch"></param>
        /// <param name="gameFont"></param>
        public DeathMatchModeLogic(NetworkSession networkSession, ContentManager content, GraphicsDevice graphicsDevice, SpriteBatch spriteBatch)
            : base(networkSession, content, graphicsDevice, spriteBatch)
        {
            // Set the total number of kills for this game.
            this.totalNumberOfKills = Program.maxKills;
        }

        #endregion

        #region Methods

        /// <summary>
        /// Get the start position in an Assault game.
        /// </summary>
        /// <param name="playerProfile"></param>
        /// <returns></returns>
        public override Vector3 GetStartPosition(PlayerProfile playerProfile)
        {
            Vector3 startPosition = playerProfile.getDeathMatchStartPosition();

            return startPosition;

        } // End of the getStartPosition method

        /// <summary>
        /// Check if the game has ended.
        /// </summary>
        /// <param name="gameTime"></param>
        /// <param name="currentMap"></param>
        public override void CheckIfGameHasEnded(GameTime gameTime, IMap currentMap)
        {
            // Variables
            int tempMaxKills = 0;

            // Calculate max kills and set the leading player.
            foreach (NetworkGamer gamer in networkSession.AllGamers)
            {
                // Look up what player is associated with this player.
                NetworkPlayerProfile networkPlayer = gamer.Tag as NetworkPlayerProfile;

                if (networkPlayer.numberOfKills > tempMaxKills)
                {
                    tempMaxKills = networkPlayer.numberOfKills;
                    this.winningPlayer = networkPlayer.playerName;
                }
            }

            // Wait to update this variable, we have to wait some time to account for latency.
            if (this.latencyTime <= 0)
            {
                // Set the max kills variable.
                this.maxKills = tempMaxKills;
            }
            else
            {
                // Decrease the latency time counter.
                this.latencyTime -= gameTime.ElapsedGameTime.Milliseconds;
                this.winningPlayer = "All players";
            }

            // Check if the game has ended, totalNumberOfKills or the end of the game time.
            if (this.maxKills >= this.totalNumberOfKills || this.totalGameTime <= 0)
            {
                // Set the game as ended.
                this.hasGameEnded = true;
            }

        } // End of the check if game has ended method.

        /// <summary>
        /// A method to calculate the number of kills.
        /// </summary>
        /// <param name="networkPlayer"></param>
        /// <param name="gameCamera"></param>
        public override void CalculateNumberOfKills(PlayerProfile networkPlayer, Camera gameCamera)
        {
            // Add one kill to the camera record, +1
            gameCamera.numberOfKills++;

        } // End of the CalculateNumberOfKills method.

        /// <summary>
        /// Draw information specific for an Assault game, this method must be called inside SpriteBatch.Begin() och SpriteBatch.End().
        /// </summary>
        /// <param name="viewPort"></param>
        /// <param name="scaleBarrel"></param>
        public override void DrawSpecific2D(Viewport viewPort, Camera gameCamera, IMap currentMap, float scaleBarrel)
        {
            // Set safe area variables.
            int safeAreaLeft = viewPort.TitleSafeArea.Left;
            int safeAreaRight = viewPort.TitleSafeArea.Right;
            int safeAreaTop = viewPort.TitleSafeArea.Top;
            int safeAreaBottom = viewPort.TitleSafeArea.Bottom;

            // Game mode string
            String gameMode = "Deathmatch";

            // Set a attacking and defender string
            String leadingPlayerString = this.maxKills.ToString() + "/" + this.totalNumberOfKills + " kills by " + this.winningPlayer;

            // Number of kills string
            String numberOfKills = "Kills: " + gameCamera.numberOfKills.ToString();

            // Draw information about the game mode
            spriteBatch.DrawString(gameFont, gameMode, new Vector2(safeAreaLeft + 10, safeAreaTop), textColor, 0,
                               Vector2.Zero, textScale, SpriteEffects.None, 0);

            // Draw number of kills.
            spriteBatch.DrawString(gameFont, numberOfKills, new Vector2(safeAreaLeft + 10, safeAreaTop + 30), textColor, 0,
                               Vector2.Zero, textScale, SpriteEffects.None, 0);

            // Number of max kills compared to total number of kills.
            spriteBatch.DrawString(gameFont, leadingPlayerString, new Vector2(safeAreaRight - (gameFont.MeasureString(leadingPlayerString).X *
                textScale) - 10, safeAreaTop), textColor, 0, Vector2.Zero, textScale, SpriteEffects.None, 0);

        } // End of the DrawSpecific2D method

        /// <summary>
        /// Update barrels on the server.
        /// </summary>
        public override void UpdateServerBarrels(NetworkPlayerProfile player, IMap currentMap, AudioManager audioManager)
        {
            // Do nothing.

        } // End of the UpdateServerBarrels method.

        /// <summary>
        /// A method used to get back to a game when a player has been dead.
        /// </summary>
        /// <param name="spawnScreen"></param>
        public override void GetBackToGame(SpawnScreen spawnScreen)
        {
            // Call the get back to game method.
            spawnScreen.GetBackToDeathMatch();

        } // End of the GetBackToGame method

        /// <summary>
        /// Add a end game screen.
        /// </summary>
        /// <param name="screenManager"></param>
        public override void AddEndGameScreen(ScreenManager screenManager)
        {
            screenManager.AddScreen(new EndGameScreen(networkSession), null);

        } // End of the AddEndGameScreen method.

        #endregion

    } // End of class

} // End of namespace
