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

public class AudioManager : SelfInstantiatingSingleton<AudioManager> {

	List<AudioSource> audioSources;
	
	public int initialObjectCount;
	
	IEnumerable<AudioSource> freeAudioSourceQuery = null;

    public bool SoundEnabled { get; set; }
	
	AudioSource NextFree {
		get {
			if(freeAudioSourceQuery == null)
				freeAudioSourceQuery = (from item in audioSources where (item.isPlaying == false) select item);
			
			AudioSource freeAudioSource = freeAudioSourceQuery.FirstOrDefault();
			
			if(freeAudioSource == null)
			{
				freeAudioSource = CreateAudioSource();
			}
			else
			{
				ResetAudioSource(freeAudioSource);
			}
			
//			Debug.Log("Returning audioSrc - clip: " + (freeAudioSource.clip == null ? "null" : freeAudioSource.clip.ToString()) + " - loop: " + freeAudioSource.loop.ToString() + " - volume: " + freeAudioSource.volume.ToString());
			
			return freeAudioSource;
		}
	}
	
	Transform myTransform;
	
	protected override void Awake() {
		base.Awake ();
		
		myTransform = transform;
		
		audioSources = new List<AudioSource>(initialObjectCount);
		
		for(int i=0; i<initialObjectCount; i++) {
			CreateAudioSource();
		}

        SoundEnabled = true;
	}
	
	//When a new scene is loaded, reset existing audio source values
	void OnLevelWasLoaded(int levelIdx) {
		if(audioSources != null) {
			for(int i=0; i<audioSources.Count; i++) {
				AudioSource audioSrc = audioSources[i];
				if(!audioSrc.isPlaying) {
					ResetAudioSource(audioSrc);
				}
			}
		}
	}

	void ResetAudioSource(AudioSource audioSrc)
	{
		audioSrc.clip = null;
		audioSrc.loop = false;
		audioSrc.volume = 1f;
		audioSrc.pitch = 1f;
		audioSrc.spread = 0f;
		audioSrc.transform.position = Vector3.zero;
	}
	
	AudioSource CreateAudioSource() {
		GameObject audioGO = new GameObject("audioSrc");
		DontDestroyOnLoad(audioGO); //Make sure this game object persists
		AudioSource audioSrc = audioGO.AddComponent<AudioSource>();
		audioSrc.playOnAwake = false;
		audioSrc.loop = false;
		
		audioSources.Add(audioSrc);
		audioSrc.transform.parent = myTransform;
		return audioSrc;
	}
	
	public AudioSource Play(AudioClip clip, float volume = 1f, float pitch = 1f, bool loop = false, Vector3 position = default(Vector3)){
        if (!SoundEnabled)
        {
            return null;
        }
		AudioSource audioSrc = NextFree;
		audioSrc.clip = clip;
		audioSrc.loop = loop;
		audioSrc.volume = volume;
		audioSrc.pitch = pitch;
		audioSrc.transform.position = position;
//		Debug.Log("Gonna play audioSrc - clip: " + (audioSrc.clip == null ? "null" : audioSrc.clip.ToString()) + " - loop: " + audioSrc.loop.ToString() + " - volume: " + audioSrc.volume.ToString());
		audioSrc.Play();
//		Debug.Log("Started playing audioSrc - clip: " + (audioSrc.clip == null ? "null" : audioSrc.clip.ToString()) + " - loop: " + audioSrc.loop.ToString() + " - volume: " + audioSrc.volume.ToString());
//		Debug.Log(string.Empty);
		return audioSrc;
	}
}