using UnityEngine;
using System.Collections;

public class s_Player : MonoBehaviour
{
	public static int turn = 1;
	
	public int doubleJumpCount = 0;
	public int repairCount = 0;
	public int tongueCount = 0;
	public Texture2D standingTex;
	public Texture2D jumpingTex;
	public GameObject ps_water;
	
	public bool lost = false; //This checks if you actually lost
	public bool lose = false; //This checks if you should lose when you stop moving, for the jumping in water
	public bool moving;
	public bool dontMove = false; //This is for when colliders are updating
	public bool usingTongue;
	
	RaycastHit hit;
	Vector3 direction;
	Vector3 velocity;
	float speed = 7.0f;
	//The platform you are jumping off of
	s_Platform jumpOffPlatform;
	//For rotating the player when jumping
	Vector3 lookPos;
	//For when you are using your tongue and checking flies
	float moveTolerance = 0.1f;
	//To check if you lost (when you aren't moving)
    Vector3 curPos;
    Vector3 lastPos; 
	
	void Start()
	{
		turn = 1;
		DoubleJumped(0); //Initial update for colliders
		
		dontMove = true;
		StartCoroutine(EnableMove()); //So you can't kill yourself as soon as it starts by jumping in the water
	}
	
	void Update()
	{	
		CheckClick();
		CheckMove();
	}
	
	void OnTriggerStay(Collider other)
	{	
		if (!dontMove && !moving && !usingTongue && jumpOffPlatform == null)
			if (other.gameObject.tag == "Platform")
				jumpOffPlatform = other.gameObject.GetComponent<s_Platform>();
	}
	
	void OnTriggerExit(Collider other)
	{
		//Jump off a platform
		if (jumpOffPlatform != null)
		{
			jumpOffPlatform.Hit();
			jumpOffPlatform = null;
		}	
	}
	
	public void DoubleJumped(int _amount)
	{
		doubleJumpCount += _amount;
		s_Controller controller = Camera.main.GetComponent<s_Controller>();
		
		//Dont want to update in start
		if (_amount != 0)
			controller.UpdateUIPowerups();
		
		GameObject[] doubleColliders = GameObject.FindGameObjectsWithTag("DoubleCollider");
		
		if (doubleJumpCount <= 0)
		{
			foreach (GameObject jumpCollider in doubleColliders)
			{
				s_Collider colliderScript = jumpCollider.GetComponent<s_Collider>();
				jumpCollider.collider.enabled = false;
				colliderScript.hitPlatform = false;
				colliderScript.hitRepair = false;
			}
		}
		else
		{
			foreach (GameObject jumpCollider in doubleColliders)
			{
				s_Collider colliderScript = jumpCollider.transform.GetComponent<s_Collider>();
				StartCoroutine(colliderScript.EnableCollider());
			}
		}
	}
	
	void CheckRepair(s_Collider col)
	{
		if (repairCount > 0)
		{
			--repairCount;
			s_Controller controller = Camera.main.GetComponent<s_Controller>();
			controller.UpdateUIPowerups();
			
			col.Repair();
			AudioManager.PlaySound(AudioManager.repair);
		}
		//else
			//CheckLose();
			//Lose();
	}
	
	void CheckTongue(s_Fly fly)
	{
		//If you have powerup
		if (tongueCount > 0)
		{
			bool result = false;
			//AND if in cardinal directions
			if (Mathf.Abs(fly.transform.position.x - transform.position.x) < moveTolerance
				|| Mathf.Abs(fly.transform.position.z - transform.position.z) < moveTolerance)
			{
				if (Mathf.Abs(fly.transform.position.x - transform.position.x) < moveTolerance)
					result = true;
				
				//rotate to fly and tongue
				direction = fly.transform.position;
				direction.y = transform.position.y; //Keep my y position
				transform.LookAt(direction);
				transform.Rotate(new Vector3(0, 180, 0)); //Need sprites to face right direction
				
				usingTongue = true;
				moving = true;
				--tongueCount;
				s_Controller controller = Camera.main.GetComponent<s_Controller>();
				controller.UpdateUIPowerups();
				
				fly.Tongue(result);
			}
		}
	}
	
	public void EnableColliders()
	{
		//Enable the things
		foreach (Transform child in transform)
		{
			//Don't check tongue or disabled colliders
			if (child.name == "Tongue" || !child.collider.enabled)
				continue;
			
			s_Collider colliderScript = child.transform.GetComponent<s_Collider>();
			StartCoroutine(colliderScript.EnableCollider());
		}
	}
	
	public IEnumerator CheckLose()
	{
		//Need to wait because it detects flies that you are about to hit and win
		yield return new WaitForSeconds(0.25f);
		
		//Check if the colliders are hitting a platform or a repairable
		foreach (Transform child in transform)
		{
			//Don't check tongue or disabled colliders
			if (child.name == "Tongue" || !child.collider.enabled)
				continue;
			
			s_Collider colliderScript = child.GetComponent<s_Collider>();
			if (colliderScript.hitPlatform && !colliderScript.hitRepair)
				yield break;
			
			if (colliderScript.hitRepair && repairCount > 0)
				yield break;
		}
		
		//Check if there are any flies you can get
		if (tongueCount > 0)
		{
			GameObject[] flies = GameObject.FindGameObjectsWithTag("Fly");
			foreach (GameObject fly in flies)
			{
				if (Mathf.Abs(fly.transform.position.x - transform.position.x) < moveTolerance
					|| Mathf.Abs(fly.transform.position.z - transform.position.z) < moveTolerance)
					yield break;
			}
		}
		
		//Last check - are you moving?
		if (curPos != lastPos || moving || usingTongue || dontMove)
		{
			Debug.Log("Do not lose, you are moving!!!!");
			yield break;
		}
		
		//You are about to lose, you just jumped into the water
		if (!lose)
			lost = true;
	}
	
	void CheckMove()
	{
		curPos = transform.position;
		if (moving && !usingTongue)
		{
			float distance = Vector3.Distance(transform.position, direction);
			if(distance > 0.0001)
			{
			    transform.position = Vector3.Lerp(
			    transform.position, direction,
			    Time.deltaTime * speed / distance);
			}
			else
			{
				StartCoroutine(EnableMove());
				dontMove = true;
				moving = false;
				renderer.material.mainTexture = standingTex;
				StartCoroutine(CheckLose());
				lastPos = curPos;
				
				//This is for if you are jumping in the water
				if (lose)
				{
            		Instantiate(ps_water, transform.position, transform.rotation);
					AudioManager.PlaySound(AudioManager.jumpInWater);
					
					renderer.enabled = false;
					
					//These are just to make it so you cant move when you jump into the water
					moving = true;
					usingTongue = true;
					
					StartCoroutine(JumpInWaterDelayLose());
				}
				else
					++turn; //Add to the turn count if you haven't jumped in the water
			}
		}	
	}
	
	IEnumerator JumpInWaterDelayLose()
	{
		yield return new WaitForSeconds(AudioManager.jumpInWater.length);
		lost = true;
	}
	
	IEnumerator EnableMove()
	{
		yield return new WaitForSeconds(0.05f);
		dontMove = false;
	}
	
	void Jump()
	{
		//Little jump
		transform.position += Vector3.forward * 0.5f;
		//Get direction
		direction = hit.collider.gameObject.transform.position;
		direction.y = transform.position.y; //Keep my y position
		lookPos = direction;
		direction -= Vector3.forward * 0.5f;
		Vector3.Normalize(direction);
		//Move
		transform.LookAt(lookPos);
		transform.Rotate(new Vector3(0, 180, 0)); //Need sprites to face right direction
		moving = true;
		renderer.material.mainTexture = jumpingTex;
	}
		
	void Lose()
	{
		//TODO jump in water
		Jump();
		Debug.Log("Jump in water!");
		lose = true;
	}
	
	void CheckClick()
	{
		if (moving || lost || dontMove)
			return;
		
		//Gets input: click for osx, windows, and editor. Touch for android and iphone
#if UNITY_EDITOR || UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_WEBPLAYER
		if (Input.GetMouseButtonDown(0))
#endif
					
#if UNITY_ANDROID && !UNITY_EDITOR || UNITY_IPHONE && !UNITY_EDITOR
		for (int i = 0; i < Input.touchCount; ++i)
            if (Input.GetTouch(i).phase.Equals(TouchPhase.Began))
#endif
						
		{
				
			//Then makes a ray, for touch or click position
#if UNITY_ANDROID && !UNITY_EDITOR || UNITY_IPHONE && !UNITY_EDITOR
 			Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(i).position);
#endif
				
#if UNITY_EDITOR || UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_WEBPLAYER
			Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
#endif
			
			//If you click on something
      		if (Physics.Raycast(ray, out hit, 100.0f))
			{
				//If you hit a fly
				if (hit.collider.gameObject.tag == "Fly")
				{
					s_Fly flyScript = hit.collider.gameObject.GetComponent<s_Fly>();
					CheckTongue(flyScript);
				}
					
				//This is for checking if you lose when hitting crocs
				//Note: it's really ugly, but if the whole thing were done this way, it would be much nicer
				if (hit.collider.gameObject.name == "PlatformCrocodileOff" || hit.collider.gameObject.name == "PlatformCrocodileOn")
				{
					float distance=(transform.position-hit.collider.gameObject.transform.position).magnitude;
						Debug.Log(distance);
					if (distance < 2.5f && distance > .5f || distance < 4.1f && distance > 3.5f)
						{}//Good
					else
						return;
							
					s_PlatformTime crocScript = hit.collider.gameObject.GetComponent<s_PlatformTime>();
						
					//Huge mystery why this transforming needs to happen, always goes -0.5z if I don't
					hit.collider.gameObject.transform.position += Vector3.forward * 0.5f;
					if (crocScript.jumpEnabled)
					{
						Debug.Log("Croc Enabled");
						if (distance < 2.5f && distance > .5f)
						{
								Debug.Log("Small Dis");
							AudioManager.PlaySound(AudioManager.jump, 0.5f);
							Jump();
						}
						else if (distance < 4.1f && distance > 3.5f && doubleJumpCount > 0)
						{
								Debug.Log("Large Dis");
							DoubleJumped(-1);
							AudioManager.PlaySound(AudioManager.doubleJump);
							Jump();
						}	
					}
					else //Croc Underwater
					{
						if (distance < 2.5f && distance > .5f)
						{
							AudioManager.PlaySound(AudioManager.jump, 0.5f);
							Jump();
							Lose();	//Croc eats em
						}
						else if (distance < 4.1f && distance > 3.5f && doubleJumpCount > 0)
						{
							DoubleJumped(-1);
							AudioManager.PlaySound(AudioManager.doubleJump);
							Jump();
							Lose();	//Croc eats em
						}	
					}
						
					hit.collider.gameObject.transform.position -= Vector3.forward * 0.5f;
						
					return;
				}
						
				
				
				//If that something happens to be one of the colliders
				if (hit.collider.gameObject.name == "PlayerCollider")
				{
					//Check if collider hit a platform
					s_Collider colliderScript = hit.collider.gameObject.GetComponent<s_Collider>();
						
					//You haven't hit a platform
					if (!colliderScript.hitPlatform)
					{
						bool checkLose = false;
							
						//Double check you can double jump if hitting a double jump before going into the water
						if (hit.collider.gameObject.tag == "DoubleCollider")
						{
							if (doubleJumpCount > 0 && colliderScript.hitPlatform)
								checkLose = true;
						}
							
						if (!checkLose)
						{
							if (hit.collider.gameObject.tag == "DoubleCollider")
								AudioManager.PlaySound(AudioManager.doubleJump);
							else
								AudioManager.PlaySound(AudioManager.jump, 0.5f);
								
							Lose();
							return;
						}
					}
					
					//Repair
					if (colliderScript.hitRepair)
					{
						CheckRepair(colliderScript);
					}
					//Jump
					else
					{	
						if (hit.collider.gameObject.tag == "DoubleCollider")
						{
							DoubleJumped(-1);
							AudioManager.PlaySound(AudioManager.doubleJump);
						}
						else
							AudioManager.PlaySound(AudioManager.jump, 0.5f);
				
						Jump();
					}
						
				}
     		}
   		}
	}
	
}
