// Converted from UnityScript to C# at http://www.M2H.nl/files/js_to_c.php - by Mike Hergaarden
// Do test the code! You usually need to change a few small bits.

using UnityEngine;
using System.Collections;

public class EyeRotation : MonoBehaviour {
    public bool random = true;
    [Header("Place this script just on one eye!")]
	public Transform otherEye;
	private Vector3 startDirection1;
	private Vector3 startDirection2;
	private Vector3 direction1;
	private Vector3 direction2;
    private float direction;
    private float directionV;
    private float offset = 10.0f;
    [HideInInspector]
	public bool  lookTarget = false;
    public Entity entity;
	private float time = 0.0f;
	private float nextChange= 0.8f;
	[Header("If you want to add eyelid movement assign these transforms")]
	public Transform upperEyelid1;
	public Transform upperEyelid2;
	public Transform lowerEyelid1;
	public Transform lowerEyelid2;
	private Vector3 upperEyelid1Rotation;
	private Vector3 upperEyelid2Rotation;
	private Vector3 lowerEyelid1Rotation;
	private Vector3 lowerEyelid2Rotation;
	private float blinkingTime= 0.0f;
	private float nextBlinkingChange = 0.8f;
    public Vector3 upperOffset = new Vector3(-30, -30, -30);
    public Vector3 lowerOffset = new Vector3(30, 30, 30);
    public float blinkingSpeed = 1.0f;

	void  Start (){
		startDirection1 = transform.localEulerAngles;
		startDirection2 = otherEye.localEulerAngles;
		direction1 = startDirection1;
		direction2 = startDirection2;
		direction = 0.0f;
		lookTarget = false;
		if (upperEyelid1!=null){
			upperEyelid1Rotation = upperEyelid1.localEulerAngles;
			upperEyelid2Rotation = upperEyelid2.localEulerAngles;
			lowerEyelid1Rotation = lowerEyelid1.localEulerAngles;
			lowerEyelid2Rotation = lowerEyelid2.localEulerAngles;
			nextBlinkingChange = Random.Range(3.0f,6.0f);
		}
        if (entity==null){
            entity = transform.root.GetComponent<Entity>();
        }
        nextChange = Random.Range(0.4f, 1.7f);
    }

	void  LateUpdate (){
        time = time + Time.deltaTime;
		if (time>nextChange){
			time = 0.0f;
			UpdateEyeDirection();
		}
        if (entity!=null){
            lookTarget = (entity.lookingTarget!=null);
        }
        if (random) {
            if (!lookTarget) {
                direction1 = RLerp(direction1, startDirection1 + new Vector3(directionV, 0, direction), Time.deltaTime * 30);
                direction2 = RLerp(direction2, startDirection2 + new Vector3(directionV, 0, direction + offset), Time.deltaTime * 30);
            }
            else {
                direction1 = RLerp(direction1, startDirection1, Time.deltaTime * 30);
                direction2 = RLerp(direction2, startDirection2 + new Vector3(0, 0, offset), Time.deltaTime * 30);
            }
            transform.localEulerAngles = direction1;
            otherEye.localEulerAngles = direction2;
        }
		if (upperEyelid1!=null){
			blinkingTime = blinkingTime+Time.deltaTime;
			if (blinkingTime>=nextBlinkingChange && blinkingTime<nextBlinkingChange+0.5f){
                float eyelidFactor = Mathf.Sin((blinkingTime-nextBlinkingChange)*Mathf.PI*4);
				upperEyelid1.localEulerAngles = RLerp(upperEyelid1Rotation, upperEyelid1Rotation + upperOffset, eyelidFactor);
				upperEyelid2.localEulerAngles = RLerp(upperEyelid2Rotation, upperEyelid2Rotation + upperOffset, eyelidFactor);
				lowerEyelid1.localEulerAngles = RLerp(lowerEyelid1Rotation, lowerEyelid1Rotation + lowerOffset, eyelidFactor);
				lowerEyelid2.localEulerAngles = RLerp(lowerEyelid2Rotation, lowerEyelid2Rotation + lowerOffset, eyelidFactor);
			}
			else if (blinkingTime>nextBlinkingChange+0.5f){
                if (blinkingSpeed <= 0.0) {
                    nextBlinkingChange = 999.0f;
                }
                else {
                    nextBlinkingChange = Random.Range(3.0f, 6.0f) / blinkingSpeed;
                }
				blinkingTime = 0.0f;
			}
			else {
				upperEyelid1.localEulerAngles = upperEyelid1Rotation;
				upperEyelid2.localEulerAngles = upperEyelid2Rotation;
				lowerEyelid1.localEulerAngles = lowerEyelid1Rotation;
				lowerEyelid2.localEulerAngles = lowerEyelid2Rotation;
			}
		}
	}

	void  UpdateEyeDirection (){
		if (otherEye!=null){
			direction = Random.Range(-15.0f,15.0f);
			directionV = Random.Range(-8.0f,2.0f);
			nextChange = Random.Range(0.4f,2.7f);
		}
	}

	Vector3 RLerp ( Vector3 from ,   Vector3 to ,   float time  ){
		Vector3 res= new Vector3(0,0,0);
		if (false){ // true = Linear Interpolation, false = Spherical Interpolation
			if (Mathf.Abs(from.x-to.x)<=180){
				res.x = Mathf.Lerp(from.x,to.x,time);
				}
			else {
				if (from.x<180)
					res.x = Mathf.Lerp(from.x+360,to.x,time);
				else
					res.x = Mathf.Lerp(from.x-360,to.x,time);
				}
			if (Mathf.Abs(from.y-to.y)<=180){
				res.y = Mathf.Lerp(from.y,to.y,time);
				}
			else {
				if (from.y<180)
					res.y = Mathf.Lerp(from.y+360,to.y,time);
				else
					res.y = Mathf.Lerp(from.y-360,to.y,time);
				}
			if (Mathf.Abs(from.z-to.z)<=180){
				res.z = Mathf.Lerp(from.z,to.z,time);
				}
			else {
				if (from.z<180)
					res.z = Mathf.Lerp(from.z+360,to.z,time);
				else
					res.z = Mathf.Lerp(from.z-360,to.z,time);
				}
			}
		else {
			Vector3 newFrom = new Vector3(0,0,0);
			if (Mathf.Abs(from.x-to.x)<=180){
				newFrom.x = from.x;
				}
			else {
				if (from.x<180)
					newFrom.x = from.x+360;
				else
					newFrom.x = from.x-360;
				}
			if (Mathf.Abs(from.y-to.y)<=180){
				newFrom.y = from.y;
				}
			else {
				if (from.y<180)
					newFrom.y = from.y+360;
				else
					newFrom.y = from.y-360;
				}
			if (Mathf.Abs(from.z-to.z)<=180){
				newFrom.z = from.z;
				}
			else {
				if (from.z<180)
					newFrom.z = from.z+360;
				else
					newFrom.z = from.z-360;
				}
			res = Vector3.Slerp(newFrom,to,time);
			}
		return res;
	}
}