using UnityEngine;
using System.Collections;
using InControl;


public class Player : MonoBehaviour
{
	// movement config
	public float gravity = -25f;
	public float runSpeed = 8f;
	public float groundDamping = 20f; // how fast do we change direction? higher means faster
	public float inAirDamping = 5f;
	public float jumpHeight = 3f;
	public int playerNum = 1;
	public bool isKnockedOut = false;
	public bool wasStomped = false;
	public bool pickedUp = false;
	public bool throwPlayer = false;
	public int stunCount = 5;
	public GameObject blurSprite;
	public Transform parentTrans;
	public Player parentObj;
	public int facingDir = 0;
	public Vector3 _velocity;
	public int livesCounter = 5;
	public TextMesh livesText;
	public GameObject livesIcon;

	[HideInInspector]
	private float normalizedHorizontalSpeed = 0;

	private CharacterController2D _controller;
	private Animator _animator;
	private RaycastHit2D _lastControllerColliderHit;
	//private Vector3 _velocity;
	private Renderer _renderer;
	private int _jumpCount = 0;
	private bool _stomping = false;
	private Player _hitPlayer;
	private int _stunCounter = 0;
	private InputDevice inputDevice;
	private Transform _transform;
	private float smoothedMovementFactor;
	private ScoreManager _scoreManager;
	private bool _isEnabled = true;




	void Awake()
	{
		_animator = GetComponent<Animator>();
		_controller = GetComponent<CharacterController2D>();
		_renderer = GetComponent<Renderer>();
		_transform = transform;

		// listen to some events for illustration purposes
		_controller.onControllerCollidedEvent += onControllerCollider;
		_controller.onTriggerEnterEvent += onTriggerEnterEvent;
		_controller.onTriggerExitEvent += onTriggerExitEvent;

		livesText.text = "x"+livesCounter.ToString();
		_scoreManager = ScoreManager.getInstance();
	}


	#region Event Listeners

	void onControllerCollider( RaycastHit2D hit )
	{
		// bail out on plain old ground hits cause they arent very interesting
		if( hit.normal.y == 1f )
			return;

		// logs any collider hits if uncommented. it gets noisy so it is commented out for the demo
		//Debug.Log( "flags: " + _controller.collisionState + ", hit.normal: " + hit.normal );
	}


	void onTriggerEnterEvent( Collider2D col )
	{
		//Debug.Log( "onTriggerEnterEvent: " + col.gameObject.name );
		if ( col.gameObject.CompareTag("Player") ){
			_hitPlayer = col.GetComponent<Player>();
			if(_stomping){
				_hitPlayer.isKnockedOut = true;
				_hitPlayer.wasStomped = true;
				_hitPlayer.renderer.sortingOrder = 10;
				_renderer.sortingOrder = 5;
			}
		}
	}

	void OnTriggerStay2D(Collider2D col) {
		if ( col.gameObject.CompareTag("Player") ){
			_hitPlayer = col.GetComponent<Player>();
			if (inputDevice != null)
			{
				if(inputDevice.Action3.IsPressed && _hitPlayer.isKnockedOut){
					_hitPlayer.pickedUp = true;
					_hitPlayer.parentTrans = _transform;
					_hitPlayer.parentObj = this;
				}
			}
		}
	}

	void onTriggerExitEvent( Collider2D col )
	{

	}

	#endregion

	void resetPlayer() {
		_velocity.x = 0;
		_velocity.y = 0;
		_stunCounter = 0;
		stunCount = 5;
		_jumpCount = 0;

		isKnockedOut = false;
		wasStomped = false;
		pickedUp = false;
		throwPlayer = false;
		parentTrans = null;
		parentObj = null;
		_stomping = false;

		if(Application.loadedLevelName =="LavaLevel"){
			_transform.position = new Vector3(3.0f, 9.75f, 0);
		}else{
			_transform.position = new Vector3(6.0f, 9.75f, 0);
		}
		--livesCounter;
		livesText.text = "x" + livesCounter.ToString();
		if(livesCounter == 0){
			this.gameObject.SetActive(false);

			if( _scoreManager.checkForWin() ){
				Application.LoadLevel("WinnerScreen");
			}
		}
	}

	public void allowJump(){
		_jumpCount = 1;
	}

	// the Update loop contains a very simple example of moving the character around and controlling the animation
	void Update()
	{	
		inputDevice = (InputManager.Devices.Count > playerNum) ? InputManager.Devices[playerNum] : null;
		if (inputDevice != null)
		{
			if(!_isEnabled){
				_isEnabled = true;
				_renderer.enabled = true;
				livesIcon.SetActive(true);
			}

			// grab our current _velocity to use as a base for all calculations
			_velocity = _controller.velocity;

			if( _controller.isGrounded ){
				_velocity.y = 0;
				_jumpCount = 0;
				if(_stomping){
					_velocity.y = Mathf.Sqrt( 2f * (jumpHeight * 0.4f) * -gravity );
					_animator.Play( Animator.StringToHash( "Jump" ) );
				}
				_stomping = false;
				blurSprite.SetActive(false);
			}

			if(_hitPlayer != null){
				if(inputDevice.Action3.WasReleased && _hitPlayer.isKnockedOut){
					_hitPlayer.pickedUp = false;
					_hitPlayer.throwPlayer = true;
					_hitPlayer.allowJump();
					AudioController.Play("tap");
				}
			}

			if(inputDevice.MenuWasPressed){
				Application.LoadLevel("StageSelect");
			}
			
			if(!isKnockedOut)
			{
				if( inputDevice.Direction.X > 0.2 )
				{
					facingDir = 1;

					normalizedHorizontalSpeed = 1;
					if( transform.localScale.x < 0f )
						transform.localScale = new Vector3( -transform.localScale.x, transform.localScale.y, transform.localScale.z );

					if( _controller.isGrounded )
						_animator.Play( Animator.StringToHash( "Run" ) );
				}
				else if( inputDevice.Direction.X < -0.2 )
				{
					facingDir = 0;

					normalizedHorizontalSpeed = -1;
					if( transform.localScale.x > 0f )
						transform.localScale = new Vector3( -transform.localScale.x, transform.localScale.y, transform.localScale.z );

					if( _controller.isGrounded )
						_animator.Play( Animator.StringToHash( "Run" ) );
				}
				else
				{
					normalizedHorizontalSpeed = 0;

					if( _controller.isGrounded )
						_animator.Play( Animator.StringToHash( "Idle" ) );
				}

				// we can only jump whilst grounded
				if( _controller.isGrounded && inputDevice.Action1.WasPressed )
				{
					_velocity.y = Mathf.Sqrt( 2f * jumpHeight * -gravity );
					_animator.Play( Animator.StringToHash( "Jump" ) );
					_jumpCount = 1;
					AudioController.Play("jump");
				}
				// double jump
				if( !_controller.isGrounded && inputDevice.Action1.WasPressed && _jumpCount == 1 ){
					_velocity.y = Mathf.Sqrt( 2f * jumpHeight * -gravity );
					_animator.Play( Animator.StringToHash( "Jump" ) );
					_jumpCount = 0;
					AudioController.Play("jump");
				}
				// stomp
				if( !_controller.isGrounded && inputDevice.Action2.WasPressed ){
					_velocity.x = 0.0f;
					_velocity.y = -30.0f;
					_stomping = true;
					blurSprite.SetActive(true);
					_animator.Play( Animator.StringToHash( "Slam" ) );
					_renderer.sortingOrder = 10;
					AudioController.Play("thud");
				}

				// apply horizontal speed smoothing it
				smoothedMovementFactor = _controller.isGrounded ? groundDamping : inAirDamping; // how fast do we change direction?
				_velocity.x = Mathf.Lerp( _velocity.x, normalizedHorizontalSpeed * runSpeed, Time.deltaTime * smoothedMovementFactor );

				// apply gravity before moving
				_velocity.y += gravity * Time.deltaTime;

				_controller.move( _velocity * Time.deltaTime );
			}
			else
			{
				blurSprite.SetActive(false);

				if(wasStomped){
					smoothedMovementFactor = _controller.isGrounded ? groundDamping : inAirDamping; // how fast do we change direction?
					_velocity.x = Mathf.Lerp( _velocity.x, normalizedHorizontalSpeed * runSpeed, Time.deltaTime * smoothedMovementFactor );
					_velocity.y = Mathf.Sqrt( 2f * (jumpHeight * 0.2f) * -gravity );
					wasStomped = false;
				}

				if(throwPlayer && parentObj != null){
					throwPlayer = false;
					
					if(parentObj.facingDir == 0){
						_velocity.x = -10.0f;
						_velocity.y = Mathf.Sqrt( 2f * (jumpHeight * 0.4f) * -gravity );
					}
					
					if(parentObj.facingDir == 1){
						_velocity.x = 10.0f;
						_velocity.y = Mathf.Sqrt( 2f * (jumpHeight * 0.4f) * -gravity );
					}
					parentObj = null;
				}

				if(!pickedUp ){
					_animator.Play( Animator.StringToHash( "Knockout" ) );
					_velocity.y += gravity * Time.deltaTime;

					smoothedMovementFactor = _controller.isGrounded ? groundDamping : inAirDamping; // how fast do we change direction?
					_velocity.x = Mathf.Lerp( _velocity.x, normalizedHorizontalSpeed * runSpeed, Time.deltaTime * smoothedMovementFactor );

					_controller.move( _velocity * Time.deltaTime );
				}else{
					if(parentObj != null){
						if(parentObj.facingDir == 0){
							_transform.position = new Vector3(parentTrans.position.x + -0.3f, parentTrans.position.y + 0.3f, parentTrans.position.z);
						}else{
							_transform.position = new Vector3(parentTrans.position.x + 0.3f, parentTrans.position.y + 0.3f, parentTrans.position.z);
						}
					}
				}
			}

			if(inputDevice.Action3.WasPressed){
				_stunCounter++;
			}
			
			if(_stunCounter >= stunCount){
				_stunCounter = 0;
				stunCount += 5;
				isKnockedOut = false;
			}

			if( _transform.position.x < -7.0f ){
				resetPlayer();
			}

			if( _transform.position.x > 17.0f ){
				resetPlayer();
			}

			if( _transform.position.y < -6.0f ){
				resetPlayer();
			}
		}
		else
		{
			if(_isEnabled){
				_isEnabled = false;
				_renderer.enabled = false;
				livesIcon.SetActive(false);
				blurSprite.SetActive(false);
			}
		}
	}

}
