using UnityEngine;
using System.Collections;

public class PlayerWater : MonoBehaviour
{
	public const int COMBO_UNLOCK			= 50;
	public const int COMBO_50_STARS			= 30;
	public const int COMBO_20_STARS			= 15;
	public const int COMBO_10_PERC_BOOST	= 10;
	public const int COMBO_5_PERC_POWER_BOOST = 5;

	public float MaxFirstHorizontalForce	= 100;
	public float MaxFirstVerticalForce		= 50;

	public float MaxHorizontalForce			= 100;
	public float MaxVerticalForce			= 50;

	private bool m_curJumpClicked			= false;
	private bool m_firstJump				= true;
	private bool m_firstClick				= true;
	private bool m_slice					= true;
	private bool m_side						= false;

	private float m_z;
	private float m_initX;
	private float m_time;
	private float m_cur;
	private float m_score;
	private float m_power					= 100;

	private Vector3 m_lastPos;
	private bool m_ended					= false;
	private int m_combo						= 0;
	private int m_stars						= 0;
	private float m_boost					= 1;
	private float m_launcher				= 0;

	public float HazardBoost				= 1;
	public float BowlTouched				= 0;
	
	private bool m_falling					= false;
	private float m_lastPosY				= 0.0f;

	public bool Ended()
	{
		return m_ended;
	}

	public void AddStars( int stars )
	{
		m_stars += stars;
	}

	void Start ()
	{
		m_initX = transform.position.x;
		m_z = transform.position.z;
	}
	
	void FixedUpdate ()
	{
		if ( m_ended )
		{
			transform.position = new Vector3( transform.position.x, transform.position.y - Time.deltaTime, transform.position.z );
			return;
		}

		transform.position = new Vector3( transform.position.x, transform.position.y, m_z );

		if ( !m_firstJump )
		{
			if ( m_lastPos != null )
			{
				if (
					transform.position.x == m_lastPos.x &&
					transform.position.y == m_lastPos.y && 
					transform.position.z == m_lastPos.z
				)
				{
					collider.isTrigger = true;
					m_ended = true;
				}
			}
			
			m_lastPos = new Vector3 ( transform.position.x, transform.position.y, transform.position.z );
		}
	}

	void Update()
	{
		if ( m_ended || m_power == 0 )
		{
			return;
		}

		if ( m_firstJump )
		{
			if ( m_slice )
			{
				if ( !m_side )
				{
					m_cur += Time.deltaTime;

					if ( m_cur > 1 )
					{
						m_cur = 1;
						m_side = true;
					}

					m_launcher = ExponentialOut( m_cur, 0, 1, 1 );
				}
				else
				{
					m_cur -= Time.deltaTime;

					if ( m_cur < 0 )
					{
						m_cur = 0;
						m_side = false;
					}
				}

				m_launcher = ExponentialIn( m_cur, 0, 1, 1 );

				if ( Space() )
				{

					rigidbody.AddForce( Vector3.up * ( MaxFirstVerticalForce * m_launcher ) );
					rigidbody.AddForce( Vector3.right * ( MaxFirstHorizontalForce * m_launcher ) );

					m_power = Mathf.Round( m_launcher * 100 );
					m_slice = false;
					m_firstJump = false;
				}
			}
		}
		else
		{
			if ( transform.position.y < m_lastPosY )
			{
				m_falling = true;
			}
			else
			{
				m_falling = false;
			}

			m_lastPosY = transform.position.y;

			if ( m_falling && !m_curJumpClicked )
			{
				if ( Space() && m_power > 0 )
				{
					m_time = Time.time;
					m_curJumpClicked = true;
				}
			}
		}

		m_score = transform.position.x - m_initX;
	}

	void Combo( float time )
	{
		if ( time < 0.2f )
		{
			m_combo++;
			Bonuses();
		}
		else
		{
			m_combo = 0;
		}
	}

	void Punishment( float time )
	{
		if ( time < 0.2f )
		{
			// WELL DONE MY FRIEND
		}
		else if ( time <= 0.4f )
		{
			PowerTake( 10 );
		}
		else if ( time <= 0.6f )
		{
			PowerTake( 15 );
		}
		else if ( time <= 0.8f )
		{
			PowerTake( 20 );
		}
		else if ( time < 1.0f )
		{
			PowerTake( 25 );
		}
		else if ( time < 1.2f )
		{
			PowerTake( 33 );
		}
		else
		{
			PowerTake( 33 );
		}
	}

	void Bonuses()
	{
		switch ( m_combo )
		{
			case COMBO_20_STARS:
				m_stars += 20;
				Debug.Log( "x15 Combo. 20 Stars!" );
				break;
			case COMBO_50_STARS:
				m_stars += 50;
				Debug.Log( "x20 Combo. 20 Stars!" );
				break;
			case COMBO_UNLOCK:
				// Unlock special equipment
				break;
		}

		if ( m_combo % COMBO_10_PERC_BOOST == 0 )
		{
			m_boost = 1.1f;
			Debug.Log( "x10 Combo. +10% Boost!" );
		}
		else if ( m_combo % COMBO_5_PERC_POWER_BOOST == 0 )
		{
			PowerAdd( 5 );
			Debug.Log( "x10 Combo. +5% Boost!" );
		}
	}

	public void PowerAdd( int add )
	{
		m_power += add;

		if ( m_power > 100 )
		{
			m_power = 100;
		}
	}

	public void PowerTake( int take )
	{
		m_power -= take;

		if ( m_power < 0 )
		{
			m_power = 0;
		}
	}

	void OnCollisionEnter( Collision collisionInfo )
	{
		if ( m_ended )
		{
			return;
		}

		if ( !m_firstJump )
		{
			if ( m_curJumpClicked )
			{
				float force = 0;
				float upforce = 0;
				float diff = ( Time.time - m_time ) * Time.timeScale;
				float time = 0;

				Combo		( diff );
				Punishment	( diff );

				time = ( m_power / 100 ) * m_boost * HazardBoost;

				if ( m_boost != 1 )
				{
					m_boost = 1;
				}

				if ( HazardBoost != 1 )
				{
					HazardBoost = 1;
				}

				if ( time > 0 )
				{
					force	= QuadraticOut( time, 0, MaxHorizontalForce, 1 * m_boost * HazardBoost );
					upforce = QuadraticOut( time, 0, MaxVerticalForce, 1 * m_boost * HazardBoost );
				}

				rigidbody.velocity = new Vector3();
				rigidbody.AddForce( Vector3.up * upforce );
				rigidbody.AddForce( Vector3.right * force );

				m_curJumpClicked = false;
			}
			else
			{
				if ( m_power > 0 )
				{
					PowerTake( 33 );

					rigidbody.AddForce( Vector3.up * ( MaxVerticalForce * 0.2f ) );
					rigidbody.AddForce( Vector3.right * ( MaxHorizontalForce * 0.2f ) );
				}
			}
		}
	}

	bool Space()
	{
		return Input.GetKey( KeyCode.Space );
	}

	bool Clicked()
	{
		return Space() || Input.GetMouseButtonDown( 0 );
	}

	bool RightClicked()
	{
		return Space() || Input.GetMouseButtonDown( 1 );
	}

	void OnGUI()
	{
		GUI.color = new Color( 0, 0, 0 );
		GUI.Label( new Rect( 0, 0, 128, 32 ), new GUIContent( "Score: " + m_score ) );
		GUI.Label( new Rect( 0, 16, 128, 32 ), new GUIContent( "Starts: " + m_stars ) );
		GUI.Label( new Rect( 128, 0, 128, 32 ), new GUIContent( "Combos: " + m_combo ) );
		GUI.Label( new Rect( 128, 16, 128, 32 ), new GUIContent( "Power: " + m_power ) );

		if ( m_firstJump )
		{
			GUI.Label( new Rect( 0, 32, 128, 32 ), new GUIContent( "Launch:" ) );

			GUI.color = new Color( 0, 255, 0 );
			GUI.VerticalSlider( new Rect( 32, 64, 32, 128 ), m_launcher, 1, 0 );
		}
		else
		{
			GUI.Label( new Rect( 0, 32, 128, 32 ), new GUIContent( "Power:" ) );

			GUI.color = new Color( 0, 255, 0 );
			GUI.VerticalSlider( new Rect( 32, 64, 32, 128 ), m_power, 100, 0 );
		}

		if ( m_ended )
		{
			GUI.color = new Color( 0, 255, 0 );

			if ( GUI.Button( new Rect( 260, 200, 128, 64 ), new GUIContent( "RETRY" ) ) )
			{
				Application.LoadLevel( "WaterJumping" );
			}

			if ( GUI.Button( new Rect( 260, 264, 128, 64 ), new GUIContent( "SELECT OTHER\nSPORT" ) ) )
			{
				Application.LoadLevel( "SportsScreen" );
			}
		}
	}

	float ExponentialIn( float t, float b, float c, float d )
	{
		return t == 0 ? b : c * Mathf.Pow( 2, 10 * ( t / d - 1 ) ) + b;
	}

	float ExponentialOut( float t, float b, float c, float d )
	{
		return t == d ? b + c : c * ( -Mathf.Pow( 2, -10 * t / d ) + 1 ) + b;
	}

	float QuadraticIn( float t, float b, float c, float d )
	{
		return c * ( t /= d ) * t + b;
	}

	float QuadraticOut( float t, float b, float c, float d )
	{
		return -c * ( t /= d ) * ( t - 2 ) + b;
	}
}
