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

namespace Util
{
	public class SoundManager : MonoBehaviour
	{
		/// <summary>
		/// Singleton. Gets the instance.
		/// </summary>
		/// <returns>The instance.</returns>
		public static SoundManager GetInstance() {
			if (null == instance) {
				GameObject go = new GameObject("SoundManager");
				instance = go.AddComponent<SoundManager>();
			}
			return instance;
		}
		static SoundManager instance;

		[SerializeField]
		List<AudioClip> bgmList;
		[SerializeField]
		List<AudioClip> seList;

		private List<AudioSource> playedBGMList = new List<AudioSource>();
		private List<AudioSource> playedSEList = new List<AudioSource>();

		void Awake() {
			bgmList = getBgmResources ();
			seList = getSeResources ();
		}

		/// <summary>
		/// Play BGM Sound (default loop)
		///  </summary>
		public void PlayBGM(string soundFileName) {
			PlayBGM (soundFileName, true);
		}

		/// <summary>
		/// Play BGM Sound
		///  </summary>
		public void PlayBGM(string soundFileName, bool isLoop) {
			// find playing audio source and play.stop
			playedBGMList.FindAll (bgm => bgm.isPlaying.Equals (true))
				.ForEach (delegate  (AudioSource _audioSource) {
					_audioSource.Stop ();
				});
			AudioSource playedBGM = playedBGMList.Find (bgm => bgm.clip.name.Equals (soundFileName));
			if (null == playedBGM) {
				playedBGM = gameObject.AddComponent<AudioSource>();
				playedBGM.clip = getBGMAudioClip(soundFileName);
				playedBGMList.Add(playedBGM); 
			}
			playedBGM.loop = isLoop;
			playedBGM.Play();
		}

		public void PlaySE (string soundFileName) {
			PlaySE (soundFileName, true);
		}

		/// <summary>
		/// Plaies the S.
		/// </summary>
		/// <param name="soundFileName">Sound file name.</param>
		/// <param name="isLoop">If set to <c>true</c> is loop.</param>
		public void PlaySE (string soundFileName, bool isLoop) {
			AudioSource playedSE = playedSEList.Find (se => se.clip.name.Equals(soundFileName));
			if (null == playedSE) {
				playedSE = gameObject.AddComponent<AudioSource>();
				playedSE.clip = getSEAudioClip(soundFileName);
				playedSEList.Add(playedSE);
			}
			playedSE.loop = isLoop;
			playedSE.Play ();
		}

		/// <summary>
		/// Stops All of the BGM.
		/// </summary>
		public void StopBGM () {
			playedBGMList.FindAll (bgm => bgm.isPlaying.Equals (true))
				.ForEach (delegate (AudioSource _audioSource) {
					_audioSource.Stop();
				});
		}

		/// <summary>
		/// Stops All of the SE.
		/// </summary>
		public void StopSE () {
			playedSEList.FindAll (se => se.isPlaying.Equals (true))
				.ForEach (delegate (AudioSource _audioSource) {
					_audioSource.Stop();
				});
		}

		/// <summary>
		/// Gets the BGM resources.
		/// </summary>
		/// <returns>The bgm resources.</returns>
		List<AudioClip> getBgmResources() {
			AudioClip[] bgmAudioClips = Resources.LoadAll<AudioClip> ("Sounds/BGM/");
			return new List<AudioClip> (bgmAudioClips);
		}

		/// <summary>
		/// Gets the SE resources.
		/// </summary>
		/// <returns>The se resources.</returns>
		List<AudioClip> getSeResources() {
			AudioClip[] seAudioClips = Resources.LoadAll<AudioClip> ("Sounds/SE/");
			return new List<AudioClip> (seAudioClips);
		}

		/// <summary>
		/// Gets the BGM audio clip.
		/// </summary>
		/// <returns>The BGM audio clip.</returns>
		/// <param name="bgmFileName">Bgm file name.</param>
		AudioClip getBGMAudioClip(string bgmFileName) {
			return bgmList.Find (bgm => bgm.name.Equals(bgmFileName));
		}

		/// <summary>
		/// Gets the SE audio clip.
		/// </summary>
		/// <returns>The SE audio clip.</returns>
		/// <param name="seFileName">Se file name.</param>
		AudioClip getSEAudioClip(string seFileName) {
			return seList.Find (se => se.name.Equals(seFileName));
		}

		// Debug
		public bool isDebug = false;
		void OnGUI() {
			if (isDebug) {
				GUILayout.BeginVertical("BGM");
				foreach (AudioClip clip in this.bgmList) {
					if (GUILayout.Button(clip.name)) {
						PlayBGM(clip.name);
					}
				}
				GUILayout.EndVertical();

				GUILayout.BeginVertical("SE");
				foreach (AudioClip clip in this.seList) {
					if (GUILayout.Button(clip.name)) {
						PlaySE(clip.name, false);
					}
				}
				GUILayout.EndVertical();
			}
		}
	}
}