using System;
using System.Drawing;

namespace Icarus.Logic.Physics
{
	/// <summary>
    /// This class handles the collision methods needed for a 
    /// physics player.  A physics player is a physics object
    /// that is used as a character.  The player controlled by
    /// the user or the enemies fighting the user are two examples
    /// oh physics players.
	/// </summary>
	public class PhysicsPlayer : WorldObject
	{

        #region Declarations
        
        /// <summary>
        /// Used to determine if player should stop walking when he hits the ground
        /// </summary>
        private bool bStopWalking;

        /// <summary>
        /// Causes the player to be hurt or not when attacked
        /// </summary>
        private bool bVulnerable;

        /// <summary>
        /// The number of engine iterations that the player is invulnerble
        /// </summary>
        private int iInvulnerableIterationLimit;

        /// <summary>
        /// The number of invulneralbe iterations so far
        /// </summary>
        private int iInvulnerableIterationCount;

        /// <summary>
        /// The number of iterations this player should flicker
        /// when they are about to die
        /// </summary>
        private int iDeathIterationLimit;

        /// <summary>
        /// The number of iterations this player has flickered
        /// </summary>
        private int iDeathInterationCount;

        #endregion
		
        #region Fields

        /// <summary>
        /// Gets or sets whether this player is vulnerable
        /// </summary>
        public bool Vulnerable
        {
            get { return this.bVulnerable; }
            set { this.bVulnerable = value; }
        }

        /// <summary>
        /// Gets or sets the limit of invulnerable iterations
        /// </summary>
        public int InvulnerableIterationLimit
        {
            get { return this.iInvulnerableIterationLimit; }
            set { this.iInvulnerableIterationLimit = value; }
        }

        /// <summary>
        /// Gets or sets the current number of invulnerable interations
        /// </summary>
        public int InvulnerableIterationCount
        {
            get { return this.iInvulnerableIterationCount; }
            set { this.iInvulnerableIterationCount = value; }
        }

        /// <summary>
        /// gets or sets the number of iterations this player will flicker while dieing
        /// </summary>
        public int DeathIterationLimit
        {
            get { return this.iDeathIterationLimit; }
            set { this.iDeathIterationLimit = value; }
        }

        /// <summary>
        /// gets or sets the number of iterations this player has flickered
        /// </summary>
        public int DeathIterationCount
        {
            get { return this.iDeathInterationCount; }
            set { this.iDeathInterationCount = value; }
        }

        /// <summary>
        /// Gets or sets a boolean used to determine if player should stop walking 
        /// when he hits the floor.
        /// </summary>
        public bool StopWalking
        {
            get { return this.bStopWalking; }
            set { this.bStopWalking = value; }
        }

        #endregion

        #region Constructors
        
        /// <summary>
        /// Instantiate a Player Object -- called a Physics Player by the
        ///  Physics Engine
        /// </summary>
        public PhysicsPlayer()
		{
            //Initially this player can get hurt
            this.bVulnerable = true;

            //Length of time to remain invulnerable
            this.iInvulnerableIterationLimit = 20; // 1/3 sec.

            //Length of time to flicker when dieing
            this.iDeathIterationLimit = 75;// 1 sec at regular engine speed

            //Invalid value for initial loop
			this.LastActionState = -1;
            this.bStopWalking = false;
		}

        #endregion

        #region Methods

        /// <summary>
        /// Starts the player walking left and puts him in the correct
        /// action state
        /// </summary>
        public virtual void walkLeft()
        {
            //Check to see if walking left is valid at this moment
            if(this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.StandingLeft
                || this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.StandingRight
                || this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingLeft
                || this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingRight
                || this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingUpSlopeLeft
                || this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingDownSlopeLeft
                || this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingUpSlopeRight
                || this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingDownSlopeRight
                || this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.JumpingRight
                || this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.JumpingLeft)
            {
                if(this.ActionState != (int)PhysicsSettings.enumPlayerActionStates.JumpingRight && 
                    this.ActionState != (int)PhysicsSettings.enumPlayerActionStates.JumpingLeft)
                {
                    //Don't stop walking
                    this.bStopWalking = false;

                    //Set action state
                    this.LastActionState = this.ActionState;
                    this.ActionState = (int)PhysicsSettings.enumPlayerActionStates.WalkingLeft;
                }
                    //Set velocity
                    this.Velocity.i = -PhysicsSettings.Instance.WalkVelocity;
                
            }
        }

        /// <summary>
        /// Starts the player walking right and puts him in the correct
        /// action states
        /// </summary>
        public virtual void walkRight()
        {
            //Check to see if walking left is valid at this moment
            if(this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.StandingLeft
                || this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.StandingRight
                || this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingLeft
                || this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingRight
                || this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingUpSlopeLeft
                || this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingDownSlopeLeft
                || this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingUpSlopeRight
                || this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingDownSlopeRight
                || this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.JumpingRight
                || this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.JumpingLeft)
            {
                if(this.ActionState != (int)PhysicsSettings.enumPlayerActionStates.JumpingRight && 
                    this.ActionState != (int)PhysicsSettings.enumPlayerActionStates.JumpingLeft)
                {
                    //Don't stop walking
                    this.bStopWalking = false;

                    //Set action state
                    this.LastActionState = this.ActionState;
                    this.ActionState = (int)PhysicsSettings.enumPlayerActionStates.WalkingRight;
                }
                //Set velocity
                this.Velocity.i = PhysicsSettings.Instance.WalkVelocity;
            }
        }

        /// <summary>
        /// Stops the player from walking if he is currently walking
        /// </summary>
        public virtual void walkStop()
        {
            if(this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingLeft)
            {
                this.Velocity.i = 0.0f;
                this.LastActionState = this.ActionState;
                this.ActionState = (int)PhysicsSettings.enumPlayerActionStates.StandingLeft;
            }
            else if(this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingRight)
            {
                this.Velocity.i = 0.0f;
                this.LastActionState = this.ActionState;
                this.ActionState = (int)PhysicsSettings.enumPlayerActionStates.StandingRight;
            }
            this.bStopWalking = true;
        }


        /// <summary>
        /// Stops the player from doing whatever it might be doing and causes it to just stand there
        /// </summary>
        public void stopAll()
        {
            //Moving left
            if((this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.StandingLeft) ||
                (this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingLeft) ||
                (this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingUpSlopeLeft) ||
                (this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingDownSlopeLeft) ||
                (this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.JumpingLeft) ||
                (this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.FallingLeft) ||
                (this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WhippingLeft))
            {
                this.Velocity.i = 0.0f;
                this.LastActionState = this.ActionState;
                this.ActionState = (int)PhysicsSettings.enumPlayerActionStates.StandingLeft;
            }
            else if((this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.StandingRight) ||
                (this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingRight) ||
                (this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingUpSlopeRight) ||
                (this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingDownSlopeRight) ||
                (this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.JumpingRight) ||
                (this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.FallingRight) ||
                (this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WhippingRight))
            {
                this.Velocity.i = 0.0f;
                this.LastActionState = this.ActionState;
                this.ActionState = (int)PhysicsSettings.enumPlayerActionStates.StandingRight;
            }
            
        }

        /// <summary>
        /// Make this player jump
        /// </summary>
       
        public virtual void jump()
        {
            if((this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.StandingLeft) ||
                (this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingLeft) ||
                (this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingUpSlopeLeft) ||
                (this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingDownSlopeLeft))
            {
                this.Velocity.j += PhysicsSettings.Instance.JumpVelocity;
                this.LastActionState = this.ActionState;
                this.ActionState = (int)PhysicsSettings.enumPlayerActionStates.JumpingLeft;
            }
            else if((this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.StandingRight) ||
                (this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingRight) ||
                (this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingUpSlopeRight) ||
                (this.ActionState == (int)PhysicsSettings.enumPlayerActionStates.WalkingDownSlopeRight))
            {
                this.Velocity.j += PhysicsSettings.Instance.JumpVelocity;
                this.LastActionState = this.ActionState;
                this.ActionState = (int)PhysicsSettings.enumPlayerActionStates.JumpingRight;
            }
            
        }

        #endregion

	}
}
