using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Events;

namespace ToolsBox.SoundManager {
    public class SoundManager : MonoBehaviour
    {
        public static SoundManager Instance;

        [Header("Audio Source Settings")]
        [SerializeField] GameObject _audioSourcePrefab;
        [SerializeField] int _audioSourcePoolSize;

        List<AudioSource> _waitingAudioSources;
        List<AudioSource> _usedAudioSources;

        [Header("Pool parents")]
        [SerializeField] GameObject _waitPoolParent;
        [SerializeField] GameObject _usedPoolParent;

        public UnityEvent test;
        void Awake()
        {
            if (Instance == null) Instance = this;
            SpawnSourcePool();

        }

        void SpawnSourcePool()
        {
            if (_audioSourcePrefab == null) return;
            _waitingAudioSources = new List<AudioSource>();
            _usedAudioSources = new List<AudioSource>();
            for (int i = 0; i < _audioSourcePoolSize; i++)
            {
                _waitingAudioSources.Add(Instantiate(_audioSourcePrefab, _waitPoolParent.transform).GetComponent<AudioSource>()); 
            }
        }

        public AudioSource PlaySound(SoundDataSO data)
        {
            if(data == null) return null;
            if(data.Clips.Count <= 0) return null;
            AudioClip clip = data.GetRandomClip();

            AudioSource source = GetWaitingSource();
            source.transform.parent = _usedPoolParent.transform;
            source.clip = clip;
            source.volume = data.Volume;
            source.outputAudioMixerGroup = data.AudioMixerGroup;

            if (data.Loop)
            {
                source.loop = data.Loop;
            }
            else
            {
                _ = StopSource(source, clip.length);
            }

            source.Play();
            return source;
        }

        public void PlaySound(SoundDataSO data, GameObject parentObject)
        {
            AudioSource source = PlaySound(data);

            source.transform.parent = parentObject.transform;
            source.transform.localPosition = Vector3.zero;
        }

        public void PlaySound(SoundDataSO data, Vector3 customPosition)
        {
            AudioSource source = PlaySound(data);

            source.transform.position = customPosition;
        }

        async Task StopSource(AudioSource source, float duration)
        {
            await Awaitable.WaitForSecondsAsync(duration);

            source.Stop();
            source.clip = null;
            source.outputAudioMixerGroup = null;
            source.loop = false;
            source.transform.parent = _waitPoolParent.transform;
            source.transform.position = Vector3.zero;
            _usedAudioSources.Remove(source);
            _waitingAudioSources.Add(source);
        }

        AudioSource GetWaitingSource()
        {
            AudioSource source = _waitingAudioSources[0];
            _waitingAudioSources.RemoveAt(0);
            _usedAudioSources.Add(source);
            return source;
        }
    }
}
