using UnityEngine;
using System.Collections.Generic;

public class Rock : MonoBehaviour {

	public GameObject particleSystemPrefab;
	new ParticleSystem particleSystem;
	const float particleStartVelocityThreshold = 0.3f;

	const float midDropSoundThresholdVelocity = -2;
	const float lowDropSoundThresholdVelocity = -1;
	const float rockCollisionAudioTimeThreshold = 0.2f;

	float lastSurfaceTime;

	MeshRenderer meshRenderer;
	Rigidbody rb;

	public LayerMask waterLayer;

	bool submerged = false;

	const int runningAverageCount = 4;
	float[] verticalVelocityHistory = new float[runningAverageCount];

	float VerticalVelocityAverage
	{
		get
		{
			float total = 0f;
			for(int i=0; i<runningAverageCount; i++)
			{
				total += verticalVelocityHistory[i];
			}
			float average = total / (float) runningAverageCount;
			return average;
		}
	}

	void Awake()
	{
		meshRenderer = GetComponent<MeshRenderer>();
		rb = GetComponent<Rigidbody>();
	}

	void Update()
	{
		for(int i=0; i<runningAverageCount-1; i++)
		{
			verticalVelocityHistory[i] = verticalVelocityHistory[i+1];
		}
		verticalVelocityHistory[runningAverageCount-1] = rb.velocity.y;

		if(particleSystem != null && particleSystem.particleCount == 0 && Time.time - lastSurfaceTime > 0.1f)
		{
			Destroy(particleSystem.gameObject);
			particleSystem = null;
		}
	}

	void CreateParticleSystem()
	{
		var particleSystemGO = Instantiate(particleSystemPrefab);
		particleSystem = particleSystemGO.GetComponent<ParticleSystem>();
		var shape = particleSystem.shape;
		shape.shapeType = ParticleSystemShapeType.MeshRenderer;
		shape.meshRenderer = GetComponent<MeshRenderer>();
		var particleSystemT = particleSystemGO.transform;
		particleSystemT.SetParent(transform);
		particleSystemT.localPosition = Vector3.zero;
		particleSystemT.localRotation = Quaternion.identity;
	}

	void OnTriggerEnter(Collider trigger)
	{
		//If the trigger doesn't belong to the water layer, early outs
		if(((1 << trigger.gameObject.layer) & waterLayer.value) == 0)
		{
			return;
		}

		if(trigger.transform.position.y > meshRenderer.bounds.min.y)
		{
			var yVel = rb.velocity.y;
			if(yVel < midDropSoundThresholdVelocity)
			{
//				Debug.Log("Mid Drop");
				AudioManager.Instance.Play(AudioClips.Instance.StoneFallIntoWaterMidGroup.Random(), 0.18f, position:transform.position).spatialBlend = 1;
			}
			else if(yVel < lowDropSoundThresholdVelocity)
			{
//				Debug.Log("Low Drop");
				AudioManager.Instance.Play(AudioClips.Instance.StoneFallIntoWaterLowGroup.Random(), 0.1f, position:transform.position).spatialBlend = 1;
			}
			else
			{
//				Debug.Log("No Drop sound");
			}
		}
	}

	void OnTriggerStay(Collider trigger)
	{
		CheckForSurface(trigger);
	}

	void OnTriggerExit(Collider trigger)
	{
		CheckForSurface(trigger);
	}

	void OnCollisionEnter(Collision col)
	{
		if(col.gameObject.layer == gameObject.layer)
		{
			float? lastCollisionTime = null;
			if(collisionTimeDictionary.ContainsKey(col.collider))
			{
				lastCollisionTime = collisionTimeDictionary[col.collider];
			}

			if(lastCollisionTime == null || Time.time - lastCollisionTime.Value > rockCollisionAudioTimeThreshold)
			{
				//Collided with a rock
				AudioManager.Instance.Play(AudioClips.Instance.StoneCollisionGroup.Random(), Random.Range(0.06f, 0.08f), position: col.contacts[0].point).spatialBlend = 1;
			}

			if(lastCollisionTime == null)
			{
				collisionTimeDictionary.Add(col.collider, Time.time);
			}
			else
			{
				collisionTimeDictionary[col.collider] = Time.time;
			}
		}
	}

	public Dictionary<Collider, float> collisionTimeDictionary = new Dictionary<Collider, float>();

	void CheckForSurface(Collider trigger)
	{
		//If the trigger doesn't belong to the water layer, early outs
		if(((1 << trigger.gameObject.layer) & waterLayer.value) == 0)
		{
			return;
		}

		if(trigger.transform.position.y > meshRenderer.bounds.center.y)
		{
			if(!submerged)
			{
				submerged = true;
			}
		}
		else
		{
			if(submerged)
			{
				submerged = false;
				lastSurfaceTime = Time.time;
				if(VerticalVelocityAverage > particleStartVelocityThreshold && (particleSystem == null || !particleSystem.isPlaying))
				{
					if(particleSystem == null)
					{
						CreateParticleSystem();
					}
					particleSystem.Play();
				}
//				Debug.Log(VerticalVelocityAverage);
			}
		}
	}
}
