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

public class AudioManager2D : MonoBehaviour
{
	public static AudioManager2D instance;

	public AudioMixerGroup soundsMixerGroup;
	public AudioMixerGroup musicMixerGroup;

	public int initialAudioSources = 10;

	public bool affectedByTimeScale = true;

	public bool enableSounds = true;

	private bool enableMusic = true;

	public bool EnableMusic {
		get {
			return this.enableMusic;
		}
		set {
			this.enableMusic = value;
			var mute = value == false;
			for (int i = 0; i < this.musicSources.Count; i++) {
				this.musicSources [i].mute = mute;
			}
		}
	}

	private List<AudioSource> soundSources;
	private List<AudioSource> musicSources;

	private float lastTimeScale = 0f;

	void Awake ()
	{
		if (instance != null) {
			GameObject.Destroy (this.gameObject);
			return;
		}

		GameObject.DontDestroyOnLoad (this.gameObject);

		instance = this;

		this.soundSources = new List<AudioSource> (this.initialAudioSources);
		for (int i = 0; i < this.initialAudioSources; i++) {
			var audioSource = gameObject.AddComponent<AudioSource> ();
			audioSource.playOnAwake = false;
			audioSource.outputAudioMixerGroup = this.soundsMixerGroup;
			this.soundSources.Add (audioSource);
		}

		this.musicSources = new List<AudioSource> (2);
		for (int i = 0; i < 2; i++) {
			var audioSource = gameObject.AddComponent<AudioSource> ();
			audioSource.playOnAwake = false;
			audioSource.outputAudioMixerGroup = this.musicMixerGroup;
			this.musicSources.Add (audioSource);
		}
	}

	void Update ()
	{
		if (this.affectedByTimeScale == true && Mathf.Abs (this.lastTimeScale - Time.timeScale) > 0.01f) {
			var ts = (Time.timeScale > 0.1) ? Time.timeScale : 1f;
			this.lastTimeScale = ts;

			for (int i = 0; i < this.soundSources.Count; i++) {
				this.soundSources [i].pitch = this.lastTimeScale;
			}
			for (int i = 0; i < this.musicSources.Count; i++) {
				this.musicSources [i].pitch = this.lastTimeScale;
			}
		}
	}

	public void PlaySound (AudioClip sound, AudioMixerGroup mixerGroup = null)
	{	
		if (this.enableSounds == false) {
			return;
		}

		AudioSource audioSource = null;
		for (int i = 0; i < soundSources.Count; i++) {
			if (this.soundSources [i].isPlaying == false) {
				audioSource = this.soundSources [i];
				break;
			}
		}

		if (audioSource == null) {
			audioSource = this.gameObject.AddComponent<AudioSource> ();
			audioSource.playOnAwake = false;
			this.soundSources.Add (audioSource);
		}

		if (mixerGroup == null) {
			mixerGroup = this.soundsMixerGroup;
		}

		audioSource.outputAudioMixerGroup = mixerGroup;

		audioSource.PlayOneShot (sound);
	}

	public void PlayMusic (AudioClip music, float fadeTime = 1f)
	{
		if (this.musicSources [0].isPlaying == false || fadeTime < 0.001f) {
			this.musicSources [0].PlayOneShot (music);
		} else {
			StartCoroutine (this.FadeMusic (music, fadeTime));
		}
	}

	private IEnumerator FadeMusic (AudioClip music, float fadeTime)
	{
		this.musicSources [1].PlayOneShot (music, 1f);

		var dt = 0f;

		while (dt < fadeTime) {
			dt += Time.unscaledDeltaTime;
			var volume = dt / fadeTime;

			this.musicSources [1].volume = volume;
			this.musicSources [0].volume = 1f - volume;
			yield return null;
		}

		this.musicSources [1].volume = 1f;
		this.musicSources [0].Stop ();

		var temp = this.musicSources [0];
		this.musicSources [0] = this.musicSources [1];
		this.musicSources [1] = temp;
	}
}
