using UnityEngine;
using System.Collections;
[RequireComponent (typeof (Rigidbody))]

public class NPCMove : MonoBehaviour {
	
	public Transform target; //Player
	public Transform cam; // Camera
	
	public float moveSpeed = 5.0f;
	public float rotSpeed = 2.0f;
	public float rayLength = 4.0f;
	public float minRange = 3.0f;
	public float maxRange = 20.0f;
	public float roamMaxTime = 5.0f;
	public float roamMaxTimeRange = 1.5f;
	public float screenDot = .8f;
	
	public bool isChasing = true;
	
	private Transform myTransform; //NPC
	private Rigidbody myRigid;
	private Vector3 myVelocity;
	
	private bool isGrounded = false;
	private bool isVisible = false;
	
	private float minRangeSqr;
	private float maxRangeSqr;
	
	private float distSqr=0.0f;
	
	private float roamTime = 0.0f;
	private float roamTimeMaxAjd = 5.0f;
	
	private Vector3 dirCalc;
	
	private PlayerHealth playerHealthScript;
	private Vignetting vignetting;
	
	enum NPC{
		Idle,
		Roaming,
		Chasing,
		Return
	}
	
	NPC myState; //NPC State
	
	void Start () {
		minRangeSqr = minRange * minRange;
		maxRangeSqr = maxRange * maxRange;
		
		myTransform = transform;
		myRigid = rigidbody;
		
		myRigid.freezeRotation = true;
		
		roamTime = 1000.0f;
		
		myState = NPC.Roaming;
		
		//InvokeRepeating("Teleport",10.0f,8.0f);
		
		GameObject targetPlayer = GameObject.Find("Player");
		
		if(targetPlayer){
			target = targetPlayer.transform;
			
			playerHealthScript = target.GetComponent<PlayerHealth>();
			vignetting = cam.GetComponent<Vignetting>();
		}
		else
			Debug.Log ("No player found");
	}
	
//	void Teleport(){
//		CheckVisible();
//		
//		if(!isVisible){
//			float distSqr = (target.position - myTransform.position).sqrMagnitude;
//				
//			if(distSqr > maxRangeSqr + 5.0f){
//				float distTeleport = maxRange + 20.0f;
//				
//				Vector3 terrainPosCheck = target.position + (myTransform.right * distTeleport);
//				terrainPosCheck.y = 5000.0f;
//				
//				RaycastHit hit;
//				
//				if(Physics.Raycast(terrainPosCheck,-Vector3.up, out hit, Mathf.Infinity)){
//					if(hit.collider.gameObject.tag =="Floor")
//						myTransform.position = hit.point + new Vector3(0,.25f,0);
//				}
//			}
//		}
//	}
	
	void DecisionCall(){
		CheckVisible();
		
		distSqr = (target.position - myTransform.position).sqrMagnitude;
		
		if(isVisible){
			
			if(distSqr > maxRangeSqr)
				myState=NPC.Roaming;
				
			else{
				RaycastHit hit;
 
                if (Physics.Linecast( myTransform.position, target.position, out hit))
                { 
                    if (hit.collider.gameObject.name == target.name)
					{
                        myState = NPC.Idle;
 
                        playerHealthScript.DecreaseHealth();
 						vignetting.chromaticAberration -= 0.05f;
						vignetting.intensity +=0.02f;
                    }
                    else
					{
                        myState = NPC.Roaming;
						

					}
                }
            }
		}
		else {
			if (distSqr > minRangeSqr)
				myState=NPC.Chasing;
			
			else
				myState=NPC.Idle;
		}
	}
	
	void Update () {
		
		DecisionCall();
		
		switch(myState){
			case NPC.Idle:	
				myTransform.LookAt(target);
				myVelocity = new Vector3(0,myRigid.velocity.y,0);
			break;
			
			case NPC.Roaming:
				roamTime += Time.deltaTime;
			
				if(roamTime >  roamTimeMaxAjd){
					roamTime =0;
					roamTimeMaxAjd = roamMaxTime + Random.Range(-roamMaxTimeRange, roamMaxTimeRange);
				
					dirCalc = Random.onUnitSphere;
					dirCalc.y = 0;
				}
			
//				playerHealthScript.IncreaseHealth();
//						
//				vignetting.chromaticAberration += 0.1f;
//						
//				if(vignetting.chromaticAberration >= -3)
//					vignetting.chromaticAberration = -3;
			
				Moving(dirCalc);
			
			break;
			
			case NPC.Chasing:
				Moving((target.position - myTransform.position).normalized);
			break;
			
			case NPC.Return:
				Moving((myTransform.position - target.position).normalized);
			break;	
		}
	}
	

	
	void CheckVisible(){
		Vector3 fwd = target.forward;
		Vector3 other = (myTransform.position - target.position).normalized;
		
		float productDot = Vector3.Dot(fwd,other);
		
		isVisible = false;
		
		if(productDot > screenDot)
			isVisible = true;
	}
	
	void Moving(Vector3 lookDir){
		
		RaycastHit hit;
		
		float sMultiplier = 0.75f;
		
		Vector3 lRayPos = myTransform.position - (myTransform.right * sMultiplier);
		Vector3 rRayPos = myTransform.position + (myTransform.right * sMultiplier);
		
		if(Physics.Raycast(lRayPos, myTransform.forward, out hit, rayLength)){
			if(hit.collider.gameObject.tag != "Floor")
				lookDir += hit.normal * 20.0f;
		}
		else if (Physics.Raycast(rRayPos, myTransform.forward, out hit, rayLength)){
			if(hit.collider.gameObject.tag != "Floor")
				lookDir += hit.normal * 20.0f;
		}
		
		Quaternion lookRot = Quaternion.LookRotation(lookDir);
		myTransform.rotation = Quaternion.Slerp( myTransform.rotation, lookRot, rotSpeed * Time.deltaTime );	
		
		//position
		myVelocity = myTransform.forward * moveSpeed;	
	}
	
	void FixedUpdate(){
		if(isGrounded)
			myRigid.velocity = myVelocity;	
	}
	
	void OnCollisionEnter(Collision col){
		if(col.collider.gameObject.tag == "Floor")
			isGrounded = true;
	}
	
	void OnCollisionStay(Collision col){
		if(col.collider.gameObject.tag == "Floor")
			isGrounded = true;
	}
	
	void OnCollisionExit(Collision col){
		if(col.collider.gameObject.tag == "Floor")
			isGrounded = true;
	}
}
