var targets : Transform[];
var target : Transform;
var moveSpeed : int = 5;
var health : int = 25;
var pauseTime : int = 5;
var killPause : int = 5;
var alertPause : int = 5;
var visibleRange : float = 60.0;
var range : float = 20.0;
var particles : ParticleEmitter;
var sparks : ParticleEmitter;
var fireRate = 1.0;
var dead : boolean = false;
var deadClone : GameObject;
var crouchTime : float = 4.0;
var crouch : boolean = false;
var crouching : boolean = false;
var sleep : boolean = false;
var hitTime : float = 4.0;
var hitTimer : float = 0.0;
var hit : boolean = false;
var paid : boolean = false;

var damageSound : AudioClip;
var gunSound : AudioClip;

private var timeSinceShot : float = 0.0;
private var isAlert : boolean = false;
private var activeTarget : int = 0;
var p_alertPause : float;
private var p_pauseTime : float;
private var moving : boolean = false;
private var firing : boolean = false;
private var pursue : boolean = false;

function Awake() {
	sparks.emit = false; //Don't emit particales when we start out
	SetRagdoll(false);
	target = GameObject.FindWithTag("Player").transform;
	if(particles)
		particles.emit = false;
	pursue = Random.value > 0.5 ? true : false;
}

function SetRagdoll (flag : boolean) {
	var rigidbodies = gameObject.GetComponentsInChildren (Rigidbody); //Get the rigidbodies
	for (var currentBody : Rigidbody in rigidbodies) { //cycle through them
    	currentBody.isKinematic = !flag;
    	currentBody.collider.isTrigger = !flag;
	}
	rigidbody.isKinematic = flag;
	collider.isTrigger = flag;
}


function Update () {
	if(!dead){
		crouchTime -= Time.deltaTime;
		if(crouchTime <= 0.0){
			crouchTime = 4.0;
			crouch = Random.value >= 0.5;
			if(!gameObject.name == "BlackPolice"){
				crouch = false;
			}
		}
	if(transform.Find("Root").GetComponent(Renderer).enabled == false){
		GetComponent(PoliceAnimation).enabled = false;
		animation.Stop();
	} else {
		GetComponent(PoliceAnimation).enabled = true;
		gameObject.tag = paid ? "PaidPolice" : "EnemyPolice";
		if(GameObject.FindWithTag("Player") && !paid){ //target the player or paidpolicel whichever's closer
			var op = GameObject.FindWithTag("Player").transform;
			var op2;
			if(gameObject.FindWithTag("PaidPolice")){
				op2 = FindClosestWithTag("PaidPolice").transform;
				if(Vector3.Distance(transform.position, op.position) <= Vector3.Distance(transform.position, op2.position)){
					target = op;
				} else {
					target = op2;
				}
			} else {
				target = GameObject.FindWithTag("Player").transform;
			}
		} else if(paid){
			p_alertPause = 10;
			if(GameObject.FindWithTag("EnemyPolice")){
				target = FindClosestWithTag("EnemyPolice").transform;
			}
		}
		
		if(p_alertPause > 0.0){
			sleep = false;
		}
		
		if(PlayerInView()){
			p_alertPause = alertPause;
		}
		if(p_alertPause > 0 && pursue){ //if we're following the player
			LookAtTarget(target); //look at the player
			if(PlayerInRange() == true){ //if we can, shoot
				firing = true; //tell PoliceAnimation we're firing
				crouching = crouch;
				moving = false; //tell PoliceAnimation we're not moving
				if(Time.time > timeSinceShot){
					timeSinceShot = Time.time + fireRate;
					Fire();
				}
			} else if(PlayerInRange() == false){
				transform.Translate(Vector3(0,0,moveSpeed*Time.deltaTime)); //move to where we can shoot
				firing = false;
				moving = true;
			}
			p_alertPause -= Time.deltaTime;
		} else if(p_alertPause > 0){
			transform.LookAt(target);
			if(PlayerInRange() == true){
				crouching = crouch;
				firing = true; //tell PoliceAnimation we're firing
				moving = false; //tell PoliceAnimation we're not moving
				if(Time.time > timeSinceShot){
					timeSinceShot = Time.time + fireRate;
					Fire();
				}
			}
		} else { //if we're not following the player
			if(targets.length > 0){ // if we have targets
				//check to see if we've reached a target
				if(p_pauseTime > 0){ //if we're at a target
					moving = false; //we're not moving
					p_pauseTime -= Time.deltaTime; //Decrement p_pauseTime
				} else { //we're moving in between targets
					moving = true; //so let PoliceAnimation know about it
					if(Vector3.Distance(transform.position, targets[activeTarget].transform.position) < 2){ //see if we're at the target
						p_pauseTime = pauseTime; //if we have, reset the pause counter
						activeTarget++; //set us toward the next target
						if(activeTarget > targets.length - 1) 
							activeTarget = 0; //if the active target is out of bounds, reset
					}
					LookAtTarget(targets[activeTarget]); //look at the active target
					transform.Translate(Vector3(0,0,moveSpeed*Time.deltaTime)); //move towards it
				}
			}
		}
	}
	}
	if(health <= 0){
		SetRagdoll(true);
		dead = true;
		var deadGuy : GameObject = Instantiate(deadClone, transform.position, transform.rotation);
		Destroy(gameObject);
	}
}

function OnCollisionEnter(collision : Collision) {
	if(collision.gameObject.tag == "MouseFist"){
		if(Input.GetButton("Fire1"))
			TakeDamage(GameObject.FindWithTag("Player").GetComponent("MouseStats").hitPower);
	}
}

function isMoving() {
	return moving;
}

function isFiring() {
	return firing;
}

function isDead() {
	return false;
}

function TakeDamage(damage : int) {
	if(audio && damageSound){
		audio.volume = 2;
		audio.clip = damageSound;
		audio.Play();
	}
	if(Time.time > hitTimer){
		hitTimer = Time.time + hitTime;
		hit = true;
		ResetHit();
	}
	health -= damage;
	p_alertPause = alertPause;
}

function ResetHit(){
	yield WaitForSeconds(animation["Hit"].length);
	hit = false;
}

function LookAtTarget (tar : Transform){	
	var temp = tar.position;
	temp.y = transform.position.y;
	transform.LookAt(temp);
}

function Die() {
}

function PlayerInView(){
	if(target && !sleep){
	playerDir = target.position - transform.position; 
	var hit : RaycastHit;
	var layerMask = 1 << 2;
	layerMask = ~layerMask; 
	if (Physics.Raycast (transform.position, playerDir, hit, playerDir.magnitude, layerMask)) { 
    	if (hit.transform.IsChildOf(target)) { 
    	   	var fov = Vector3.Angle(transform.TransformDirection (Vector3.forward), playerDir);
    	   	if (fov < 90) { 
    	   		if (playerDir.magnitude < visibleRange) { 
    	   		   return true;
    	   		} 
			} 
    	} 
   	}
	}
   	return false;
}

function PlayerInRange() : boolean {
	if(PlayerInView()){
		if(Vector3.Distance(transform.position, target.transform.position) < range){
			return true;
		} else {return false;}
	}
}

function Fire(){
	if(audio && gunSound){
		audio.volume = 1;
		audio.clip = gunSound;
		audio.Play();
	}
	sparks.Emit();
	var targetPosF = target.position;
	targetPosF.x += Random.value;
	targetPosF.y += Random.value;
	targetPosF.z += Random.value;
	transform.Find("Gun").LookAt(targetPosF);
	var direction = transform.Find("Gun").TransformDirection(Vector3.forward);
	var hit : RaycastHit;
	var layerMask = 1 << 2;
	layerMask = ~layerMask;
	if(Physics.Raycast(transform.Find("Gun").position, direction, hit, 20, layerMask)) {
		if(hit.rigidbody){
			if(hit.transform.IsChildOf(target)){
				target.rigidbody.AddForce(1000 * direction);
				if(target.GetComponent("MouseStats")){
					target.GetComponent("MouseStats").TakeDamage(target.GetComponent("MouseStats").machineGunDamage);	
				}
			} else {
				hit.rigidbody.AddForceAtPosition(10 * direction, hit.point);
			}
		}
		if(particles && hit.transform.IsChildOf(target)){ //if we shot the player, emit some blood
			particles.transform.rotation = Quaternion.FromToRotation(Vector3.up, hit.normal);
			particles.transform.position = hit.point;
			particles.Emit();
		}
	}
}

function FindClosestWithTag (aTag : String) : GameObject {
    // Find all game objects with tag Enemy
    var gos : GameObject[];
    gos = GameObject.FindGameObjectsWithTag(aTag); 
    var closest : GameObject; 
    var distance = Mathf.Infinity; 
    var position = transform.position; 
    // Iterate through them and find the closest one
    for (var go : GameObject in gos)  { 
        var diff = (go.transform.position - position);
        var curDistance = diff.sqrMagnitude; 
        if (curDistance < distance) { 
            closest = go; 
            distance = curDistance; 
        } 
    } 
    return closest;    
}

@script AddComponentMenu("Police/Police AI")