using UnityEngine;
using System.Collections;

public class Player : MonoBehaviour {

	#region Singleton
	private static Player instance;
	private void SetInstance()
	{
		if (instance) {
			instance.enabled = false;
		}
		instance = this;
	}
	#endregion
	#region Control Flags
	static bool forward;
	static bool backward;
	static bool left;
	static bool right;
	static bool rRight;
	static bool rLeft;
	static bool rollMode;

	static public void UpdateControls(bool forward, bool backward, 
	                                  bool left, bool right, 
	                                  bool rRight, bool rLeft, 
	                                  bool rollMode)
	{
		Player.forward 	= forward;
		Player.backward = backward;
		Player.left 	= left;
		Player.right 	= right;
		Player.rRight 	= rRight;
		Player.rLeft 	= rLeft;
		Player.rollMode = rollMode;
	}
	#endregion
	#region Control Variables
	[SerializeField]
	private float moveAbility;
	[SerializeField]
	private float rotateAbility;
	[SerializeField]
	private float rollAbility;
	[SerializeField]
	private ForceMode forceMode;
	#endregion
	#region Slots
	[SerializeField]
	private Rigidbody targetRigidBody;
	[SerializeField]
	private Rigidbody targetRigidBodyROLL;
	[SerializeField]
	private Transform targetTransform;
	[SerializeField]
	private Transform mainCamera;
	#endregion
	#region Init
	void Awake()
	{
		SetInstance ();
	}
	void Start()
	{
		mainCamera = Camera.main.transform.parent;
	}
	#endregion
	#region Update
	void FixedUpdate(){

		if (!targetRigidBody || !targetRigidBody || !mainCamera || !targetRigidBodyROLL)
			return;

		// Transform relative to the main camera.
		if (rollMode)
		{
			if (forward) {
				targetRigidBodyROLL.AddTorque((targetRigidBodyROLL.transform.right * Time.fixedDeltaTime * rollAbility),forceMode);
			}
			if (backward) {
				targetRigidBodyROLL.AddTorque((-targetRigidBodyROLL.transform.right * Time.fixedDeltaTime * rollAbility),forceMode);
			}
			if (left) {
				targetRigidBodyROLL.AddTorque((-targetRigidBodyROLL.transform.up * Time.fixedDeltaTime * rollAbility),forceMode);
			}
			if (right) {
				targetRigidBodyROLL.AddTorque((targetRigidBodyROLL.transform.up * Time.fixedDeltaTime * rollAbility),forceMode);
			}
			if (rLeft) {
				targetRigidBodyROLL.AddTorque((-targetRigidBodyROLL.transform.forward * Time.fixedDeltaTime * rollAbility),forceMode);
			}
			if (rRight) {
				targetRigidBodyROLL.AddTorque((targetRigidBodyROLL.transform.forward * Time.fixedDeltaTime * rollAbility),forceMode);
			}
		}
		else
		{
			if (forward) {
				targetRigidBody.AddForce((mainCamera.forward * Time.fixedDeltaTime * moveAbility),forceMode);
			}
			if (backward) {
				targetRigidBody.AddForce((-mainCamera.forward * Time.fixedDeltaTime * moveAbility),forceMode);
			}
			if (left) {
				targetRigidBody.AddForce((-mainCamera.right * Time.fixedDeltaTime * moveAbility),forceMode);
			}
			if (right) {
				targetRigidBody.AddForce((mainCamera.right * Time.fixedDeltaTime * moveAbility),forceMode);
			}
			if (rLeft) {
				mainCamera.Rotate (Vector3.up, rotateAbility * Time.fixedDeltaTime);
			}
			if (rRight) {
				mainCamera.Rotate (Vector3.up, -rotateAbility * Time.fixedDeltaTime);
			}
		}
	}
	#endregion
	#region Static Utility Functions
	public static Vector3 position
	{
		get
		{
			return instance? instance.targetTransform.position : Vector3.zero;
		}
		set
		{
			if (!instance)
			{
				return;
			}
			instance.transform.position = value;
		}
	}
	public static Vector3 velocity
	{
		get
		{
			return (instance && instance.targetRigidBody)? instance.targetRigidBody.velocity : Vector3.zero;
		}
		set
		{
			if (!instance || !instance.targetRigidBody)
			{
				return;
			}
			instance.targetRigidBody.velocity = value;
		}
	}

	public static Player Instance {
		get {
			return instance;
		}
	}
	#endregion
}
