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

public class AudioManager : MonoBehaviour
{
    public static AudioManager Instance;

    [SerializeField] private AudioMixerGroup masterMixerGroup;
    [SerializeField] private AudioMixerGroup musicMixerGroup;
    [SerializeField] private AudioMixerGroup ambienceMixerGroup;
    [SerializeField] private AudioMixerGroup sfxMixerGroup;

    [SerializeField] private Sound[] sounds;
    [SerializeField] private AudioSource sfxObject;
    private List<GameObject> listOfObjects = new List<GameObject>();

    private void Awake()
    {

        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }

        //
        foreach (Sound s in sounds)
        {
            s.source = gameObject.AddComponent<AudioSource>();
            s.source.clip = s.clip;

            s.source.volume = s.volume;

            switch (s.audioType)
            {
                case Sound.AudioTypes.Master:
                    s.source.outputAudioMixerGroup = masterMixerGroup;
                    break;
                case Sound.AudioTypes.Music:
                    s.source.outputAudioMixerGroup = musicMixerGroup;
                    break;
                case Sound.AudioTypes.Ambience:
                    s.source.outputAudioMixerGroup = ambienceMixerGroup;
                    break;
                case Sound.AudioTypes.SFX:
                    s.source.outputAudioMixerGroup = sfxMixerGroup;
                    break;
            }

            s.source.loop = s.loop;
            s.source.playOnAwake = s.onAwake;

            if (s.onAwake)
                s.source.Play();
        }
    }

    public void PlaySound(string clipname)
    {
        Sound s = Array.Find(sounds, sound => sound.clipName == clipname);
        if (s == null)
        {
            Debug.LogError("Sound: " + clipname + " not found!");
            return;
        }
        s.source.Play();
    }

    public void SpawnSoundEffect(AudioClip clip, Transform loc, int maxSoundDist, GameObject obj)
    {
        AudioSource audioSource = Instantiate(sfxObject, loc.position, Quaternion.identity); // Spawn Object
        audioSource.transform.parent = obj.transform; // Set parent
        audioSource.clip = clip; // Assign audioclip
        audioSource.volume = GameManager.Instance.SfxVolume; // Set audio
        audioSource.spatialBlend = 1; // Set spatialblend
        audioSource.maxDistance = maxSoundDist; // Set maxdistance
        audioSource.rolloffMode = AudioRolloffMode.Linear; // Set roll off mode
        audioSource.Play(); // Play Sound
        float clipLength = audioSource.clip.length; // Get length of clip
        Destroy(audioSource.gameObject, clipLength); // Destroy audio when audio is finished

        // Footsteps
        if(audioSource.transform.parent.name == "Player")
            listOfObjects.Add(audioSource.gameObject);
        DeleteFromList();
    }

    public void SpawnAmbience(AudioClip clip, Transform loc, int maxSoundDist, bool onAwake, bool isLooping, GameObject obj)
    {
        AudioSource audioSource = Instantiate(sfxObject, loc.position, Quaternion.identity); // Spawn Object
        audioSource.transform.parent = obj.transform; // Set parent
        audioSource.clip = clip; // Assign audioclip
        audioSource.volume = GameManager.Instance.AmbienceVolume; // Set audio
        audioSource.spatialBlend = 1; // Set spatialblend
        audioSource.maxDistance = maxSoundDist; // Set maxdistance
        audioSource.playOnAwake = onAwake; // Check if sound is played on awake or not
        audioSource.loop = isLooping; // Check if sound is looping or not
        audioSource.rolloffMode = AudioRolloffMode.Linear; // Set roll off mode
        audioSource.Play(); // Play Sound
        float clipLength = audioSource.clip.length; // Get length of clip
        if(!isLooping)
            Destroy(audioSource.gameObject, clipLength); // Destroy audio when audio is finished
    }

    private void DeleteFromList()
    {
        for (int i = 0; i < listOfObjects.Count; i++)
        {
            if(listOfObjects.Count > 2)
            {
                Destroy(listOfObjects[i].gameObject);
                listOfObjects.Remove(listOfObjects[i]);
            }
        }
    }

    public void DestroySound(GameObject obj, AudioClip clip)
    {
        for (int i = 0; i < obj.transform.childCount; i++)
        {
            if(obj.transform.GetChild(i).gameObject.GetComponent<AudioSource>().clip == clip)
            {
                Destroy(obj.transform.GetChild(i).gameObject);
            }
        }
    }

    public void UpdateMixerVolume()
    {
        masterMixerGroup.audioMixer.SetFloat("MasterVolume", Mathf.Log10(GameManager.Instance.MasterVolume)* 20);
        sfxMixerGroup.audioMixer.SetFloat("SfxVolume", Mathf.Log10(GameManager.Instance.SfxVolume)* 20);
        musicMixerGroup.audioMixer.SetFloat("MusicVolume", Mathf.Log10(GameManager.Instance.MusicVolume)* 20);
        ambienceMixerGroup.audioMixer.SetFloat("AmbienceVolume", Mathf.Log10(GameManager.Instance.AmbienceVolume)* 20);
    }
}