#region File Description
//-----------------------------------------------------------------------------
// GameplayScreen.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using System.Threading;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
#endregion

namespace GhostArena6
{
    class GameplayScreen : GameScreen
    {
        ContentManager _content;

        Texture2D _level;
        Texture2D _healthbar;
        Texture2D _healthbarBorder;

        Rectangle _rectHealthBorder;

        Vector2 _levelLocation;
        Vector2 _scoreLocation;

        SpriteFont _scoreFont;

        EntityManager _entityManager;

        FrameRateCounter _framerate;

        int _remainingTime;
        float _timeCounter;

        int _difficulty;
        int _curLevel;
        Vector2 _curLevelLoc;

        string _displayMinutes;
        
        private AchievementManager _achievementManager;
       
        public GameplayScreen(int difficulty)
        {
            TransitionOnTime = TimeSpan.FromSeconds(1.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);

            _timeCounter = 0.0f;

            _remainingTime = 180;

            _difficulty = difficulty;

            _curLevel = 1;
        }

        public override void Initialize()
        {
            ((Game1)ScreenManager.Game).SetDifficulty(_difficulty);

            _entityManager = new EntityManager(ScreenManager.Game);
            _entityManager.Initialize();

            _levelLocation = new Vector2(0, Game1.LevelTop);
            _scoreLocation = new Vector2(900, 32);

            _curLevelLoc = new Vector2(10, 10);

            _rectHealthBorder = new Rectangle(ScreenManager.Game.Window.ClientBounds.Width / 2 - 101, 10, 202, 18);

            _framerate = new FrameRateCounter(ScreenManager.Game);
            ScreenManager.Game.Components.Add(_framerate);

            //need to set action functions then enable
            IInputSystem input = ((IInputSystem)ScreenManager.Game.Services.GetService(typeof(IInputSystem)));

            input.SetActionFunction("Move", Move);
            input.SetActionFunction("Move Foward", MoveForward);
            input.SetActionFunction("Move Backward", MoveBackward);
            input.SetActionFunction("Move Left", MoveLeft);
            input.SetActionFunction("Move Right", MoveRight);
            input.SetActionFunction("Fire", Fire);
            input.SetActionFunction("Rotate", Rotate);
            input.SetActionFunction("Stop", Stop);

            input.Enable();

        }

        public override void LoadGraphicsContent(bool loadAllContent)
        {

            if (loadAllContent)
            {
                if (_content == null)
                    _content = new ContentManager(ScreenManager.Game.Services);

                _level = _content.Load<Texture2D>("Content/level");
                _scoreFont = _content.Load<SpriteFont>("Content/data");
                _healthbar = _content.Load<Texture2D>("Content/healthbar");
                _healthbarBorder = _content.Load<Texture2D>("Content/healthbarborder");

            }
        }

        public override void UnloadGraphicsContent(bool unloadAllContent)
        {
            if (unloadAllContent)
            {
                _content.Unload();
            }

            ScreenManager.Game.Components.Remove(_framerate);
        }

        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
                                                       bool coveredByOtherScreen)
        {
            base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);

            _framerate.Update(gameTime);

            if (IsActive)
            {
                _entityManager.Update(gameTime);

                if (_entityManager.IsPlayerDead())
                    DoGameOver();

                _timeCounter += gameTime.ElapsedGameTime.Milliseconds;

                if (_timeCounter >= 1000.0f)
                {
                    _remainingTime--;
                    _timeCounter -= 1000.0f;

                    if (_remainingTime == 0)
                        DoNextLevel();
                }
            }
        }

        void DoGameOver()
        {
            MessageBoxScreen messageBox = new MessageBoxScreen("Game Over. Final score: " + _entityManager.Score.ToString());

            messageBox.Accepted += GameOverMessageBoxAccepted;

            ScreenManager.AddScreen(messageBox);

            HighScoreList scores = new HighScoreList();
            scores.AddScore(new HighScore(DateTime.Now.ToShortDateString(), _curLevel, _entityManager.Score));
            scores.Save();

            if (_achievementManager != null)
                _achievementManager.Save();
        }

        void DoNextLevel()
        {
            //check for level-based achievements
            if (_achievementManager == null)
                _achievementManager = new AchievementManager(ScreenManager.Game);

            //touched
            if (!_entityManager.PlayerTouched)
            {
                if (!_achievementManager.IsAchievementEarned(Achievements.Dodger))
                    _achievementManager.AddAchievement(Achievements.Dodger);
            }
            
            //died
            if (!_entityManager.PlayerDied)
            {
                if (!_achievementManager.IsAchievementEarned(Achievements.Unstoppable))
                    _achievementManager.AddAchievement(Achievements.Unstoppable);
            }
                        
            //par time - right now just 2 1/2 minutes, could be changed to less time for higher levels
            if (_remainingTime>=150)
            {
                if (!_achievementManager.IsAchievementEarned(Achievements.QuickDead))
                    _achievementManager.AddAchievement(Achievements.QuickDead);
            }
            
            //hit/miss ratio
            float ratio = _entityManager.GetPlayerHitMissRatio();

            //just 95% right now, could be changed for higher levels
            if (ratio >= 0.95f)
            {
                if (!_achievementManager.IsAchievementEarned(Achievements.EagleEye))
                    _achievementManager.AddAchievement(Achievements.EagleEye);
            }
            

            _curLevel++;
            _remainingTime = 180;

            //increase ghost speed
            ((Game1)ScreenManager.Game).Difficulty.IncreaseGhostSpeed();

        }

        void GameOverMessageBoxAccepted(object sender, EventArgs e)
        {
            LoadingScreen.Load(ScreenManager, LoadMainMenuScreen, false);
        }

        void LoadMainMenuScreen(object sender, EventArgs e)
        {
            ScreenManager.AddScreen(new MainMenuScreen());
        }

        public override void HandleInput(InputState input, GameTime gameTime)
        {
            if (input == null)
                throw new ArgumentNullException("input");

            if (input.PauseGame)
            {
                // If they pressed pause, bring up the pause menu screen.
                ScreenManager.AddScreen(new PauseMenuScreen());
            }
        }

        private void Move(object value, GameTime gameTime)
        {
            _entityManager.MovePlayer((Direction)value);
        }

        private void MoveForward(object value, GameTime gameTime)
        {
            if (value != null)
            {
                if ((ButtonState)value == ButtonState.Pressed)
                {
                    _entityManager.MovePlayer(_entityManager.GetPlayerDirection());
                }
            }
        }

        private void MoveBackward(object value, GameTime gameTime)
        {
            if (value != null)
            {
                if ((ButtonState)value == ButtonState.Pressed)
                {
                    Direction dir = _entityManager.GetPlayerDirection();

                    if (dir < Direction.South)
                        dir += 4;
                    else
                        dir = (Direction)((int)Direction.NorthWest - (int)dir);

                    _entityManager.MovePlayer(dir);
                }
            }
        }

        private void MoveLeft(object value, GameTime gameTime)
        {
            if (value != null)
            {
                if ((ButtonState)value == ButtonState.Pressed)
                {
                    Direction dir = _entityManager.GetPlayerDirection();

                    if (dir < Direction.East)
                        dir += 6;
                    else
                        dir = (Direction)((int)Direction.NorthWest - (int)dir);

                    _entityManager.MovePlayer(dir);
                }
            }
        }

        private void MoveRight(object value, GameTime gameTime)
        {
            if (value != null)
            {
                if ((ButtonState)value == ButtonState.Pressed)
                {
                    Direction dir = _entityManager.GetPlayerDirection();

                    if (dir < Direction.West)
                        dir += 2;
                    else
                        dir = (Direction)((int)Direction.NorthWest - (int)dir);

                    _entityManager.MovePlayer(dir);
                }
            }
        }

        private void Rotate(object value, GameTime gameTime)
        {
            //need to cast object to Vector2 here
            if (value != null)
            {
                _entityManager.SetPlayerDirection((Direction)value);
            }
        }

        private void Stop(object value, GameTime gameTime)
        {
            _entityManager.StopPlayer();
        }

        private void Fire(object value, GameTime gameTime)
        {
            _entityManager.PlayerFire();
        }

        public override void Draw(GameTime gameTime)
        {
            ScreenManager.GraphicsDevice.Clear(ClearOptions.Target, Color.Black, 0, 0);

            Vector2 timeLoc = new Vector2(ScreenManager.GraphicsManager.PreferredBackBufferWidth / 2 -
                                            _scoreFont.MeasureString("Time Remaining: " + _remainingTime.ToString()).X / 2, 40.0f);

            ScreenManager.SpriteBatch.Begin();
            ScreenManager.SpriteBatch.Draw(_level, _levelLocation, Color.White);
            ScreenManager.SpriteBatch.Draw(_healthbarBorder, _rectHealthBorder, Color.White);
            ScreenManager.SpriteBatch.Draw(_healthbar, new Rectangle(_rectHealthBorder.Left + 1, _rectHealthBorder.Top + 1, _entityManager.GetPlayerHealth() * 2, 16), Color.White);
            ScreenManager.SpriteBatch.DrawString(_scoreFont, "score: " + _entityManager.Score.ToString(), _scoreLocation, Color.White);

            _displayMinutes = _remainingTime >= 60 ? ((int)(_remainingTime / 60)).ToString() : "";
            ScreenManager.SpriteBatch.DrawString(_scoreFont, "Time Remaining: " + _displayMinutes + ":" + ((int)(_remainingTime % 60)).ToString("00"), timeLoc, Color.Red);

            ScreenManager.SpriteBatch.DrawString(_scoreFont, "Level: " + _curLevel.ToString(), _curLevelLoc, Color.White);

            ScreenManager.SpriteBatch.End();

            _entityManager.Draw(gameTime);

            _framerate.Draw(gameTime);

            // If the game is transitioning on or off, fade it out to black.
            if (TransitionPosition > 0)
                ScreenManager.FadeBackBufferToBlack(255 - TransitionAlpha);
        }
    }
}
