using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class MeController : MonoBehaviour {


	private enum Dimension
	{
		TOP, SIDE, PERP
	}
	public bool isAlive = true;
	public float speed = 500f;
	public float maxAccel = 6f;
	public float jumpForce = 10000f;
	private Dimension dimension;
	public Camera camTop;
	public Camera camSide;
	private Scaler scaler;
	private float distToGround;
	private ParticleSystem ps;
	public bool canSide = false;
	public Vector3 spawnPoint;
	private TimeManager tim;
	public bool showTime = false;
	public AudioSource jump;
	public AudioSource change;
	
	
	void Start () {

		tim = GameObject.FindGameObjectWithTag("GameController").GetComponent<TimeManager>();
		scaler = GameObject.FindGameObjectWithTag ("level").GetComponent<Scaler> ();
		camTop = GameObject.FindGameObjectWithTag ("top").GetComponent<Camera> ();
		camSide = GameObject.FindGameObjectWithTag ("side").GetComponent<Camera> ();

		camTop.enabled = true;
		camSide.enabled = false;
		dimension = Dimension.TOP;
		scaler.SwitchColliders(false);
		SwitchColour();
		distToGround = collider.bounds.extents.y;
		ps = GetComponentInChildren<ParticleSystem>();

		if (transform.position.x > 50) SwitchDimension ();
		if (transform.position.x > 100) canSide = true;
	}


	void Update () {

		if (isAlive) {
			// Debug
			//		Vector3 l = new Vector3(transform.position.x-transform.localScale.x/2+0.1f, transform.position.y, transform.position.z-10);
			//		Vector3 r = new Vector3(transform.position.x+transform.localScale.x/2-0.1f, transform.position.y, transform.position.z-10);
			//		Vector3 t = new Vector3(transform.position.x, transform.position.y+0.9f, transform.position.z-10);
			//		Vector3 b = new Vector3(transform.position.x, transform.position.y-0.9f, transform.position.z-10);
			//		Vector3 c = new Vector3(transform.position.x, transform.position.y, transform.position.z-10);
			//		Debug.DrawRay (l, Vector3.forward * 20, Color.green);
			//		Debug.DrawRay (r, Vector3.forward * 20, Color.green);
			//		Debug.DrawRay (t, Vector3.forward * 20, Color.green);
			//		Debug.DrawRay (b, Vector3.forward * 20, Color.green);
			//		Debug.DrawRay (c, Vector3.forward * 20, Color.green);
			//
			//		Vector3 l2 = new Vector3(transform.position.x-transform.localScale.x/2+0.1f, transform.position.y, transform.position.z);
			//		Vector3 r2 = new Vector3(transform.position.x+transform.localScale.x/2-0.1f, transform.position.y, transform.position.z);
			//		Vector3 t2 = new Vector3(transform.position.x, transform.position.y, transform.position.z+transform.localScale.z/2-0.1f);
			//		Vector3 b2 = new Vector3(transform.position.x, transform.position.y, transform.position.z-transform.localScale.x/2+0.1f);
			//		Vector3 c2 = new Vector3(transform.position.x, transform.position.y, transform.position.z);
			//		Debug.DrawRay (l2, Vector3.up * 10, Color.green);
			//		Debug.DrawRay (r2, Vector3.up * 10, Color.green);
			//		Debug.DrawRay (t2, Vector3.up * 10, Color.green);
			//		Debug.DrawRay (b2, Vector3.up * 10, Color.green);
			//		Debug.DrawRay (c2, Vector3.up * 10, Color.green);



			// Switch plane
			if (Input.GetKeyDown (KeyCode.E) && canSide) {
				change.Play();
				camTop.enabled = !camTop.enabled;
				camSide.enabled = !camSide.enabled;

				dimension = (camTop.enabled) ? Dimension.TOP : Dimension.SIDE;
				switch (dimension) {
				case Dimension.SIDE:
						scaler.SwitchColliders (true);
						SwitchColour ();
						CheckSideCollisions ();
						break;
				case Dimension.TOP:
						scaler.SwitchColliders (false);
						SwitchColour ();
						CheckTopCollisions ();
						break;
				}
			}

			// Movement
			if (Input.GetAxis ("Horizontal") != 0) {
				rigidbody.AddForce (new Vector3 (Input.GetAxis ("Horizontal") * Time.deltaTime * speed, 0, 0));
			}
			if (Input.GetAxis ("Vertical") != 0 && dimension != Dimension.SIDE) {
				rigidbody.AddForce (new Vector3 (0, 0, Input.GetAxis ("Vertical") * Time.deltaTime * speed));
			}

			if (Input.GetButtonDown ("Jump") && dimension == Dimension.SIDE && isGrounded ()) {
				jump.Play ();
				rigidbody.AddForce (new Vector3 (0, Input.GetAxis ("Jump") * Time.deltaTime * jumpForce, 0));
			}

			// Speed limit
			Vector3 tempVel = rigidbody.velocity;
			if (Mathf.Abs (tempVel.x) > maxAccel) {
					if (tempVel.x > 0)
							tempVel.x = maxAccel;
					if (tempVel.x < 0)
							tempVel.x = -maxAccel;
			}
			if (Mathf.Abs (tempVel.z) > maxAccel) {
					if (tempVel.z > 0)
							tempVel.z = maxAccel;
					if (tempVel.z < 0)
							tempVel.z = -maxAccel;
			}
			rigidbody.velocity = tempVel;
		}
	}

	bool isGrounded() {
		return Physics.Raycast(transform.position, -Vector3.up, distToGround + 0.1f);
	}

	void SwitchColour() {
		if (dimension == Dimension.SIDE) renderer.material.color = new Color (0.725f, 0.059f, 0.059f, 1.0f);
		if (dimension == Dimension.TOP) renderer.material.color = new Color (0.882f, 0.706f, 0.118f, 1.0f);
	}

	void CheckSideCollisions() {

		RaycastHit[] leftHits;
		leftHits = Physics.RaycastAll(new Vector3(transform.position.x-transform.localScale.x/2+0.1f, transform.position.y, transform.position.z - 10), transform.forward, 500.0F, 1 << LayerMask.NameToLayer("Death"));

		RaycastHit[] rightHits;
		rightHits = Physics.RaycastAll(new Vector3(transform.position.x-transform.localScale.x/2-0.1f, transform.position.y, transform.position.z - 10), transform.forward, 500.0F, 1 << LayerMask.NameToLayer("Death"));

		RaycastHit[] topHits;
		topHits = Physics.RaycastAll(new Vector3(transform.position.x, transform.position.y+0.9f, transform.position.z - 10), transform.forward, 500.0F, 1 << LayerMask.NameToLayer("Death"));

		RaycastHit[] bottomHits;
		bottomHits = Physics.RaycastAll(new Vector3(transform.position.x, transform.position.y-0.9f, transform.position.z - 10), transform.forward, 500.0F, 1 << 8);

		RaycastHit[] centerHits;
		centerHits = Physics.RaycastAll(new Vector3(transform.position.x+transform.localScale.x/2, transform.position.y, transform.position.z - 10), transform.forward, 500.0f, 1 << LayerMask.NameToLayer("Death"));

		if (leftHits.Length > 0 || rightHits.Length > 0 || topHits.Length > 0 || bottomHits.Length > 0 || centerHits.Length > 0) {
			print("side");
			Die();
		}
	}

	void CheckTopCollisions() {
		
		RaycastHit[] leftHits;
		leftHits = Physics.RaycastAll(new Vector3(transform.position.x-transform.localScale.x/2+0.1f, transform.position.y, transform.position.z), transform.up, 500.0F, 1 << LayerMask.NameToLayer("Death"));
		
		RaycastHit[] rightHits;
		rightHits = Physics.RaycastAll(new Vector3(transform.position.x-transform.localScale.x/2-0.1f, transform.position.y, transform.position.z), transform.up, 500.0F, 1 << LayerMask.NameToLayer("Death"));
		
		RaycastHit[] topHits;
		topHits = Physics.RaycastAll(new Vector3(transform.position.x, transform.position.y, transform.position.z+transform.localScale.z/2-0.1f), transform.up, 500.0F, 1 << LayerMask.NameToLayer("Death"));
		
		RaycastHit[] bottomHits;
		bottomHits = Physics.RaycastAll(new Vector3(transform.position.x, transform.position.y, transform.position.z-transform.localScale.z/2+0.1f), transform.up, 500.0F, 1 << 8);
		
		RaycastHit[] centerHits;
		centerHits = Physics.RaycastAll(new Vector3(transform.position.x+transform.localScale.x/2, transform.position.y, transform.position.z - 10), transform.up, 500.0f, 1 << LayerMask.NameToLayer("Death"));

		
		if (leftHits.Length > 0 || rightHits.Length > 0 || topHits.Length > 0 || bottomHits.Length > 0 || centerHits.Length > 0) {
			ps.transform.position = new Vector3(ps.transform.position.x, 10, ps.transform.position.z);
			Die();
		}
	}

	public void Die() {
		transform.DetachChildren();
		ps.startColor = renderer.material.color;
		ps.Emit(50);
		ps.GetComponent<ParticleDestroy> ().Destroy ();
		tim.spawnPoint = spawnPoint;
		tim.SpawnMe();
		Destroy (gameObject);
	}

	public void SwitchDimension() {
		change.Play ();
		camTop.enabled = !camTop.enabled;
		camSide.enabled = !camSide.enabled;
		dimension = (camTop.enabled) ? Dimension.TOP : Dimension.SIDE;

		switch(dimension)
		{
		case Dimension.SIDE:
			scaler.SwitchColliders(true);
			SwitchColour();
			CheckSideCollisions();
			break;
		case Dimension.TOP:
			scaler.SwitchColliders(false);
			SwitchColour();
			CheckTopCollisions();
			break;
		}
	}

	public void ForceSideView() {
		change.Play ();
		camTop.enabled = false;
		camSide.enabled = true;
		dimension = Dimension.SIDE;

		scaler.SwitchColliders(true);
		SwitchColour();
		CheckSideCollisions();
	}
}
