using System.Collections;
using System.Collections.Generic;
using Assets.Scripts.Gameplay;
using UnityEngine;

namespace Assets.Scripts.CarController
{
	public class CarAudio : MonoBehaviour {


		public enum EngineAudioOptions // Options for the engine audio
		{
			Simple, // Simple style audio
			FourChannel // four Channel audio
		}

		public EngineAudioOptions engineSoundStyle = EngineAudioOptions.FourChannel;
		public AudioClip lowAccelClip;                                              // Audio clip for low acceleration
		public AudioClip lowDecelClip;                                              // Audio clip for low deceleration
		public AudioClip highAccelClip;                                             // Audio clip for high acceleration
		public AudioClip highDecelClip;                                             // Audio clip for high deceleration
		public float pitchMultiplier = 1f;                                          // Used for altering the pitch of audio clips
		public float lowPitchMin = 1f;                                              // The lowest possible pitch for the low sounds
		public float lowPitchMax = 6f;                                              // The highest possible pitch for the low sounds
		public float highPitchMultiplier = 0.25f;                                   // Used for altering the pitch of high sounds
		public float maxRolloffDistance = 500;                                      // The maximum distance where rollof starts to take place
		public float dopplerLevel = 1;                                              // The mount of doppler effect used in the audio
		public bool useDoppler = true; 

		private AudioSource _LowAccel; // Source for the low acceleration sounds
		private AudioSource _LowDecel; // Source for the low deceleration sounds
		private AudioSource _HighAccel; // Source for the high acceleration sounds
		private AudioSource _HighDecel; // Source for the high deceleration sounds
		private bool _StartedSound; // flag for knowing if we have started sounds
		private CarController _CarController; // Reference to car we are controlling

		private float _pitch;


		private void StartSound()
		{
			// get the carcontroller ( this will not be null as we have require component)
			_CarController = GetComponent<CarController>();

			// setup the simple audio source
			_HighAccel = SetUpEngineAudioSource(highAccelClip);

			// if we have four channel audio setup the four audio sources
			if (engineSoundStyle == EngineAudioOptions.FourChannel)
			{
				_LowAccel = SetUpEngineAudioSource(lowAccelClip);
				_LowDecel = SetUpEngineAudioSource(lowDecelClip);
				_HighDecel = SetUpEngineAudioSource(highDecelClip);
			}

			// flag that we have started the sounds playing
			_StartedSound = true;
		}

		void Update () 
		{
			if (!_StartedSound)
			{
				StartSound();
			}

			if (_StartedSound)
			{
				// The pitch is interpolated between the min and max values, according to the car's revs.
				_pitch = ULerp(lowPitchMin, lowPitchMax, _CarController.Speed / _CarController.MaxSpeed);

				// clamp to minimum pitch (note, not clamped to max for high revs while burning out)
				_pitch = Mathf.Min(lowPitchMax, _pitch);

				if (_CarController.Gear == 0 || _CarController.Clutch >= 0.7F) 
				{
					_pitch = ULerp(lowPitchMin, lowPitchMax, _CarController.Throttle);
					/*if (_CarController.Rpm > 600) {
						//_pitch = lowPitchMax;
						_pitch = ULerp(lowPitchMin, lowPitchMax, _CarController.Throttle);
					} else {
						_pitch = lowPitchMin;
					}
					*/

				}
				if (engineSoundStyle == EngineAudioOptions.Simple)
				{
					// for 1 channel engine sound, it's oh so simple:
					_HighAccel.pitch = _pitch*pitchMultiplier*highPitchMultiplier;
					_HighAccel.dopplerLevel = useDoppler ? dopplerLevel : 0;
					_HighAccel.volume = 1;
				}
				else
				{
					// for 4 channel engine sound, it's a little more complex:

					// adjust the pitches based on the multipliers
					_LowAccel.pitch = _pitch*pitchMultiplier;
					_LowDecel.pitch = _pitch*pitchMultiplier;
					_HighAccel.pitch = _pitch*highPitchMultiplier*pitchMultiplier;
					_HighDecel.pitch = _pitch*highPitchMultiplier*pitchMultiplier;

					// get values for fading the sounds based on the acceleration
					float accFade = Mathf.Abs(_CarController.Acceleration);
					float decFade = 1 - accFade;

					// get the high fade value based on the cars speed
					float highFade = Mathf.InverseLerp(0.2f, 0.8f, _CarController.Speed / _CarController.MaxSpeed);
					float lowFade = 1 - highFade;

					// adjust the values to be more realistic
					highFade = 1 - ((1 - highFade)*(1 - highFade));
					lowFade = 1 - ((1 - lowFade)*(1 - lowFade));
					accFade = 1 - ((1 - accFade)*(1 - accFade));
					decFade = 1 - ((1 - decFade)*(1 - decFade));

					// adjust the source volumes based on the fade values
					_LowAccel.volume = lowFade*accFade;
					_LowDecel.volume = lowFade*decFade;
					_HighAccel.volume = highFade*accFade;
					_HighDecel.volume = highFade*decFade;

					// adjust the doppler levels
					_HighAccel.dopplerLevel = useDoppler ? dopplerLevel : 0;
					_LowAccel.dopplerLevel = useDoppler ? dopplerLevel : 0;
					_HighDecel.dopplerLevel = useDoppler ? dopplerLevel : 0;
					_LowDecel.dopplerLevel = useDoppler ? dopplerLevel : 0;
				}
			}
		}

		private AudioSource SetUpEngineAudioSource(AudioClip clip)
		{
			AudioSource source = gameObject.AddComponent<AudioSource> ();
			source.clip = clip;
			source.volume = 0;
			source.loop = true;

			source.time = Random.Range (0F, clip.length);
			source.Play ();
			source.minDistance = 5;
			source.dopplerLevel = 0;
			return source;
		}

		// unclamped versions of Lerp and Inverse Lerp, to allow value to exceed the from-to range
		private static float ULerp(float from, float to, float value)
		{
			return (1.0f - value)*from + value*to;
		}

	    void OnTriggerExit(Collider other)
	    {
            //reset level
	    }
}

}
