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

public class Pickup : MonoBehaviour
{
	public float kickSpeed = 2;
	public float ejectTime = 1;
	public float lifeTime = 10;
	public float flashTime = 2.0f;
	public float flashHZ = 12;

	Rigidbody body;
	Renderer rend;
	Item item;
	int quantity;
	float kickTimer = 99;
	Vector3 initialSource, initialTarget;
	float ejectYVel;

	public bool isSpawned { get { return body.useGravity; } }

	void Awake() {
		body = GetComponent<Rigidbody>();
		rend = gameObject.GetComponentInChildren<Renderer>();
		item = GetComponent<Item>();
		if (!item)
			Debug.LogError("Pickup has no item to award.", gameObject);

		// Because we can also appear in the inventory, disable stuff
		// that shouldn't be used there.
		body.useGravity = false;
		quantity = 0;
	}

	public void Spawn(int value) {
		quantity = value;

		// Make us uncollectable while we eject.
		body.useGravity = true;
		body.isKinematic = true;
		body.detectCollisions = false;

		// Try and aim right at the player, as we know that's
		// going to be a valid collision spot to exist in.
		initialSource = initialTarget = transform.position;
		if (PlayerControl.current) {
			initialTarget = PlayerControl.current.transform.position;
			initialTarget += Vector3.right*0.05f;
		}

		// Solve for ejection velocity.
		float a = Physics.gravity.y;
		float t = ejectTime;
		float x = initialTarget.y - initialSource.y;
		ejectYVel = (x - 0.5f*a*t*t)/t;

		StartCoroutine(Eject());
	}

	IEnumerator Eject() {
		// Eject the pickup into the world.
		float t = 0;
		while (t < ejectTime) {
			yield return null;
			t += Time.deltaTime;

			// Follow the ejection parabola exactly.
			float mix = t / ejectTime;
			float a = Physics.gravity.y;
			transform.position = new Vector3(
				Mathf.Lerp(initialSource.x, initialTarget.x, mix),
				initialSource.y + ejectYVel*t + 0.5f*a*t*t,
				Mathf.Lerp(initialSource.z, initialTarget.z, mix));
		}

		// Make us collectable again.
		body.isKinematic = false;
		body.detectCollisions = true;

		// If we're a short-lived pickup, start counting down.
		if (lifeTime > 0) {
			yield return new WaitForSeconds(lifeTime - flashTime);
			Color c = rend.material.color;
			float cycle = 1.0f / flashHZ;
			for (int i = 0; i<flashTime/cycle; i++) {
				rend.enabled = false;
				yield return new WaitForSeconds(cycle*0.5f);
				rend.enabled = true;
				yield return new WaitForSeconds(cycle*0.5f);
			}
			GameObject.Destroy(gameObject);
		}
	}

	void OnCollisionStay(Collision coll)
    {
		if (!isSpawned)
			return;

		kickTimer += Time.deltaTime;

		PlayerControl pc = coll.gameObject.GetComponent<PlayerControl>();
		if (pc && pc.enabled) {
			Entity entity = pc.GetComponent<Entity>();

			// Give the player as many as we can, keep the rest.
			quantity -= entity.Award(item, quantity);
			if (quantity <= 0) {
				GameObject.Destroy(gameObject);
			} else {
				// If we weren't picked up, give it a kick.
				if (kickTimer > 0.5f) {
					body.AddForce(Vector3.up*kickSpeed, ForceMode.VelocityChange);
					kickTimer = 0;
				}
			}
		}
    }
}
