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 Assault game.
    /// </summary>
    public class AssaultModeLogic : GameModeLogic
    {
        #region Instance variables

        // Variables that are specific to a Assault game.
        public Texture2D alertSign;
        public String winningTeam;

        #endregion

        #region Constructors

        /// <summary>
        /// Create new logic for an Assault game.
        /// </summary>
        /// <param name="networkSession"></param>
        /// <param name="content"></param>
        /// <param name="graphicsDevice"></param>
        /// <param name="spriteBatch"></param>
        /// <param name="gameFont"></param>
        public AssaultModeLogic(NetworkSession networkSession, ContentManager content, GraphicsDevice graphicsDevice, SpriteBatch spriteBatch)
            : base(networkSession, content, graphicsDevice, spriteBatch)
        {
            // Load content
            this.alertSign = content.Load<Texture2D>("Textures/alert");
        }

        #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.getAssaultStartPosition();

            return startPosition;

        } // End of the getStartPosition method

        /// <summary>
        /// Check if the game has ended.
        /// </summary>
        /// <param name="currentMap"></param>
        public override void CheckIfGameHasEnded(GameTime gameTime, IMap currentMap)
        {
            // Check if the game has ended
            if (currentMap.numberOfBarrels == 0 || this.totalGameTime <= 0)
            {
                // Set the game as ended.
                this.hasGameEnded = true;

                if (currentMap.numberOfBarrels == 0)
                    this.winningTeam = "Attackers";
                else
                    this.winningTeam = "Defenders";
            }

        } // 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 if the player is on a different team
            // and -1 if the player is on the same team.
            if (networkPlayer.isAttacking != gameCamera.isAttacking)
            {
                gameCamera.numberOfKills++;
            }
            else
            {
                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;

            // Set a attacking and defender string
            String attackerDefender = "Attacking team";
            if (gameCamera.isAttacking == false)
                attackerDefender = "Defending team";

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

            // Barrels left string
            String barrelsLeft = currentMap.numberOfBarrels + " barrels left";

            // Draw team information
            spriteBatch.DrawString(gameFont, attackerDefender, new Vector2(safeAreaLeft + 10, safeAreaTop), textColor, 0,
                               Vector2.Zero, textScale, SpriteEffects.None, 0);

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

            // Barrels left
            spriteBatch.DrawString(gameFont, barrelsLeft, new Vector2(safeAreaRight - (gameFont.MeasureString(barrelsLeft).X * textScale) - 10,
                safeAreaTop), textColor, 0, Vector2.Zero, textScale, SpriteEffects.None, 0);

            // Draw alert sign for barrels.
            for (int b = 0; b < currentMap.items.Length; b++)
            {
                if (currentMap.items[b] != null)
                {
                    int barrelX = (int)(currentMap.items[b].boundingSpheres[0].Center.X / 100);
                    int barrelY = (int)(currentMap.items[b].boundingSpheres[0].Center.Z / 100);

                    spriteBatch.Draw(alertSign, new Vector2(safeAreaLeft + 10 + barrelX + 64, safeAreaBottom - 139 + barrelY + 64), null, Color.White, 0, new Vector2(8, 8),
                    scaleBarrel, 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)
        {
            byte barrelToRemove = 100;

            // Check for collision with barrels.
            barrelToRemove = currentMap.CollisionCheckItemOnServer(player, audioManager);

            if (barrelToRemove != 100)
            {
                // Set the datatype variable, 3: barrel data.
                byte dataType = 3;

                // Write the barrel to remove in a network packet.
                packetWriter.Write(dataType);
                packetWriter.Write(barrelToRemove);

                // Send the data to everyone in the session.
                LocalNetworkGamer server = (LocalNetworkGamer)networkSession.Host;

                server.SendData(packetWriter, SendDataOptions.Reliable);
            }

        } // 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.GetBackToAssaultGame();

        } // 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, this.winningTeam), null);

        } // End of the AddEndGameScreen method.

        #endregion

    } // End of class

} // End of namespace
