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

public class ShipController : MonoBehaviour {

	public GameObject Ship;
	public int Health = 1;
	public float InitialSpeed = 1;
	public float Speed;
	private Rigidbody rigid;
	public GameObject ShotPrefab;
	public AnimationCurve BackOnTrackEasing;
	private bool backing;

	public float LeanInFactor = 1;
	public AnimationCurve PropUpEasing;
	public float PropUpSpeed = 2;

	public GameObject[] Sails;

	[Header("Input Settings")]
	public float TurnSpeed = 1;
	public float WaterFricton = 0.95F;
	public float ShotForce = 1;


	void setSailsScale(float newScale) {
		foreach(GameObject s in Sails) {
			Vector3 scale = s.transform.localScale;
			scale.z = newScale*2.2F;
			s.transform.localScale = scale;
		}
	}

	public virtual void Awake() {
	
	}
	void Start() {
		SetUp();
	}


	
	

	public virtual void Shoot(Vector3 dir) {
		GameObject shot = Instantiate(ShotPrefab,transform.position,ShotPrefab.transform.rotation) as GameObject;
		shot.GetComponent<Rigidbody>().AddForce(dir*ShotForce+rigid.velocity,ForceMode.Impulse);
		Destroy(shot,10);
	}

	public virtual void TurnLeft() {
		Vector3 torq = new Vector3(0,-TurnSpeed,0);
		rigid.AddRelativeTorque(torq,ForceMode.Force);
	}

	void ApplyZRotation() {
		Vector3 rot = Ship.transform.localRotation.eulerAngles;
		rot.z = rigid.angularVelocity.y*LeanInFactor;
		Ship.transform.localRotation = Quaternion.Euler(-rot);
		//rigid.AddTorque(new Vector3(0,0,rigid.angularVelocity.y*LeanInFactor));
	}

	public virtual void TurnRight() {
		Vector3 torq = new Vector3(0,TurnSpeed,0);
		rigid.AddRelativeTorque(torq,ForceMode.Force);
	}

	// Use this for initialization
	public virtual void SetUp () {
		rigid = GetComponent<Rigidbody>();
		Speed = InitialSpeed;
	}
	
	
	public virtual void FixedUpdate () {
		
		rigid.AddForce(getMoveDir()*rigid.mass,ForceMode.Force);
		ApplyFriction();
		if(Ship != null) {
			ApplyZRotation();
		}

		/*
		if(transform.forward.z <= 0.1F && !backing) {
			BackOnTrack();
		}
		*/
	}

	public virtual void LateUpdate() {
		if(Ship != null) {
			PropUpLoop();
		}
	}


	void PropUpLoop() {
		float currentZRot = Ship.transform.localRotation.z;
		if(currentZRot > 180) {
		float dir = (currentZRot > 0) ? -1 : 1;
			Ship.transform.RotateAround(Ship.transform.position,Ship.transform.forward,dir*PropUpSpeed);
			Vector3 r = transform.rotation.eulerAngles;
			r.x = 0;
			Ship.transform.rotation = Quaternion.Euler(r);
		}
		
	}


/*
	void BackOnTrack() {
		backing = true;
		rigid.angularVelocity = Vector3.zero;
		StopCoroutine("BackOnTrackRoutine");
		StartCoroutine(BackOnTrackRoutine(2F));
	}


	IEnumerator BackOnTrackRoutine(float duration) {
		float l,e;
		Quaternion startRot = transform.rotation;
		Quaternion endRot = Quaternion.identity;
		for(float f = 0; f < duration; f+=Time.deltaTime) 
		{
			l = Mathf.InverseLerp(0,duration,f);
			e = Utils.Ease.GetEase(BackOnTrackEasing,l);

			transform.rotation = Quaternion.Lerp(startRot,endRot,e);
			yield return null;
		}
		backing = false;
	}
*/

	public virtual void ApplyFriction() {
		rigid.velocity *= WaterFricton;
	}

	public virtual Vector3 getMoveDir() {
		Vector3 res = Vector2.zero;
		float diff = getDirDifference();
		setSailsScale(diff);
		//res.y =  Speed*diff*WindManager.instance.Direction.sqrMagnitude;
		res += Camera.main.transform.up*Speed*diff;

		return res;
	}

	public virtual void PropUp() {
		//StopCoroutine("PropUpRoutine");
		StartCoroutine(PropUpRoutine(PropUpSpeed));
	}

	public virtual IEnumerator PropUpRoutine(float duration) {
		float l,e;
		Vector3 iniRot = transform.localRotation.eulerAngles;
		Vector3 targetRot = iniRot;
		targetRot.z = 0;

		for(float f = 0; f < duration; f+=Time.deltaTime) {
			Vector3 currRot = transform.localRotation.eulerAngles;
			iniRot.y = currRot.y;
			iniRot.x = currRot.x;
			targetRot.y = currRot.y;
			targetRot.x = 0;
			l = Mathf.InverseLerp(0,duration,f);
			e = Utils.Ease.GetEase(PropUpEasing,l);

			transform.localRotation = Quaternion.Lerp(Quaternion.Euler(iniRot),Quaternion.Euler(targetRot),e);

			yield return null;
		}
		transform.localRotation = Quaternion.Euler(targetRot);
	}


	public virtual float getDirDifference() {
		Vector2 wind = new Vector2(WindManager.instance.Direction.x,WindManager.instance.Direction.z);
		Vector2 ship = new Vector2(Camera.main.transform.up.x,Camera.main.transform.up.z);

		float diff = Vector2.Angle(wind,ship);		
		//float diff = Vector3.AngleBetween(transform.forward,WindManager.instance.Direction);
		float res = 1-Mathf.InverseLerp(0,180,diff);
		return res;

	}


	public virtual void OnCollisionEnter(Collision col) {
		
	}

	public void TakeDamage(int damage) {
		Health = Health-damage;
			if(Health <= 0) {
				DestroyMe();
			}
			UpdateDamageVisual();
	}

	public virtual void UpdateDamageVisual() {

	}
	
	public virtual void DestroyMe() {
		Destroy(this.gameObject);
	}
}
