using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using System.Diagnostics;

namespace MegaManRipoff.MainGameClasses
{
    /// <summary>
    /// Generates Pipi birds periodically for as long as the defined area is on screen.
    /// </summary>
    class PipiGenerator : Entity
    {
        #region Member Variables

        /// <summary>
        /// The effective area of this Pipi generator.
        /// </summary>
        Rectangle _area;

        /// <summary>
        /// Keeps track of the length of time to wait, in ticks, before attempting to create a Pipi bird.
        /// </summary>
        int _timer;

        /// <summary>
        /// The length of time to wait, in ticks, between each Pipi bird generations.
        /// </summary>
        static int _timeBetweenGenerations;

        /// <summary>
        /// Holds the centre point of the camera at the instant when the last Pipi bird was generated.
        /// </summary>
        Vector2 _lastGenerationPoint;

        /// <summary>
        /// Holds the maximum distance that the camera (and thus the player) can travel since the last
        /// generation point before it creates another Pipi bird. This will stop the player from just
        /// running away from all of the Pipi birds.
        /// </summary>
        static float _distanceThreshold;

        #endregion

        /// <summary>
        /// Creates a new Pipi generator.
        /// </summary>
        /// <param name="room">The current room.</param>
        /// <param name="area">The effective area of the generator.</param>
        public PipiGenerator(Room room, Rectangle area)
            : base(room, new Vector2(area.Left, area.Top))
        {
            _area = area;

            //Set up timing stuff.
            _timer = 5;
            _lastGenerationPoint = _room.Camera.FocusPoint;
        }

        #region Methods

        /// <summary>
        /// Initialise the Pipi generator's static properties based on the difficulty setting.
        /// </summary>
        /// <param name="gameDifficulty">The game's current difficulty setting.</param>
        new public static void Initialise(GameDifficulty gameDifficulty)
        {
            switch (gameDifficulty)
            {
                case GameDifficulty.Easy:
                    _timeBetweenGenerations = 750;
                    _distanceThreshold = 416;
                    break;
                case GameDifficulty.Hard:
                    _timeBetweenGenerations = 500;
                    _distanceThreshold = 288;
                    break;
                default:
                    _timeBetweenGenerations = 500;
                    _distanceThreshold = 320;
                    break;
            }
        }

        /// <summary>
        /// This method exists so that a NotImplementedException isn't thrown.
        /// </summary>
        protected override void InitialiseAnimations()
        {
            //Do nothing - the Pipi generator doesn't have animations.
        }

        /// <summary>
        /// Handles the logic for generating Pipi birds.
        /// </summary>
        private void GeneratePipiBirds()
        {
            //If we're in the camera's view, generate a Pipi bird whenever the timer hits
            //zero or the player moves too far from the previous generation point, whichever
            //comes first.
            if (_room.Camera.IsInView(_area) && (--_timer <= 0
                || Math.Abs(Vector2.Distance(_room.Camera.FocusPoint, _lastGenerationPoint)) > _distanceThreshold))
            {
                if (_room.PlayerOne != null)
                {
                    //Get the opposite to the player's direction. Also, if the bird
                    //is to be created facing right, it needs to come in from the left
                    //side of the screen, and vice versa.
                    Direction newDirection;
                    int newXPosition;

                    if (_room.PlayerOne.CurrentDirection == Direction.Right)
                    {
                        newDirection = Direction.Left;
                        newXPosition = _room.Camera.Area.Right - 2;
                    }
                    else
                    {
                        newDirection = Direction.Right;
                        newXPosition = _room.Camera.Area.Left + 2;
                    }

                    //Create the new Pipi bird.
                    _room.Add(new PipiBird(_room,
                                           new Vector2(newXPosition,
                                                       _room.Camera.Area.Top),
                                           newDirection));

                    //Set the new generation point.
                    _lastGenerationPoint = _room.Camera.FocusPoint;
                }

                //Reset the timer.
                _timer = _timeBetweenGenerations;
            }
        }

        /// <summary>
        /// Updates the Pipi generator.
        /// </summary>
        /// <param name="gameTime">The current snapshot of time.</param>
        public override void Update(GameTime gameTime)
        {
            GeneratePipiBirds();
        }

        /// <summary>
        /// This method exists so that a NotImplementedException isn't thrown.
        /// </summary>
        /// <param name="spriteBatch">The sprite batch to not draw to.</param>
        public override void Draw(SpriteBatch spriteBatch)
        {
            //Do nothing.
        }

        #endregion
    }
}
