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

[Serializable]
public struct MovementEntry
{
	public float time;
	public Vector2 direction;
	public float angle;
}

public class FlyingMovementController : MonoBehaviour {
	public bool VertLockedRelativeToPlayer;
	public float HorizSpeed;
	public float VertSpeed;
	public float HorizAccel;
	public float VertAccel;
	public bool FaceToMovement;
	public float TurnSpeed=180;
	public float StartingAngle=180;
	public List<MovementEntry> Moves;
	public float ChanceFlipHoriz=0;

	public float StartupDelay=0;

	private Vector2 targetSpeed;
	private float targetAngle;
	private float startTime;
	private int flip=1;

	private Transform player;
	private GameController gc;

	// Use this for initialization
	void Start () {
		GameObject go = GameObject.Find ("GameController");
		gc = go.GetComponent<GameController>();

		GameObject pgo = GameObject.Find("Player");
		if(pgo!=null)
			player = pgo.transform;

		targetSpeed = new Vector2(0,0);
		transform.eulerAngles = new Vector3(0, 0, StartingAngle);
		startTime = Time.fixedTime + StartupDelay;

		if(gc.rand.NextDouble() < ChanceFlipHoriz)
			flip = -1;
	}
	
	void FixedUpdate () {
		if(player == null)
		{
			GameObject pgo = GameObject.Find("Player");
		   	if(pgo!=null)
				player = pgo.transform;
			else
				return;
		}

		CheckTargets();
		if(FaceToMovement)
			TargetRotationToMovement();
		AccelToTargetSpeed();
//		RotateToTargetAngle();
	}

	private void TargetRotationToMovement()
	{
		Vector2 diff = rigidbody2D.velocity;
		float dx = diff.x;
		float dy = diff.y;
		targetAngle = Mathf.Atan2(dx, dy) * -180/Mathf.PI;
	}

	private void CheckTargets()
	{
		Vector2 target = new Vector2(0,0);
		float time = Time.fixedTime - startTime;
		foreach(MovementEntry m in Moves)
		{
			if(time>m.time)
			{
				target = m.direction;
				targetAngle = m.angle;
			}
			else
				break;
		}
		float y =  target.y * VertSpeed;

		if(VertLockedRelativeToPlayer)
		{
			y += player.rigidbody2D.velocity.y;
			if(y > 1 && transform.position.y - player.position.y > 8)  // let player catch up
			{
				Debug.Log (name + " clipped y speed to 1 to let player catch up");
				y = 1;
			}
		}
		targetSpeed = new Vector2(flip*target.x * HorizSpeed, y);
	}

	private void AccelToTargetSpeed()
	{
		Vector2 tdelta = targetSpeed - (Vector2)rigidbody2D.velocity;
		Vector2 delta = new Vector2( Mathf.Clamp(tdelta.x, -HorizAccel, HorizAccel), Mathf.Clamp(tdelta.y, -VertAccel, VertAccel));

		Vector2 force = rigidbody2D.mass * delta / Time.fixedDeltaTime;
		rigidbody2D.AddForce(force);
	}

	private void RotateToTargetAngle()
	{
		float curr = transform.eulerAngles.z;
		float turn = Mathf.DeltaAngle(curr, targetAngle);
		float max = TurnSpeed * Time.fixedDeltaTime;
		float go = Mathf.Clamp(turn, -max, max);
		transform.eulerAngles += new Vector3(0,0,go);
	}
}
