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

public class AudioController : MonoBehaviour {
    public AudioSource audioA;
    public AudioSource audioB;
    public AudioSource audioCurrent;
    public SwipeDetect swiper;
    public GameController controller;
    public float minPitch,maxPitch;
    public float divisor;
    public int pitchVariationSemitone;
    public float currentPitchVariation;
    public bool firstPatternLoaded;
    public float pitchChangeFrame, pitchError;
    public float pitchChangeSteps;
    public float volumeChangeFrame;
    public float volumeChangeSteps;
    public AudioClip[] audioClips;
    public AudioClip startingClip;
    private bool runningCoroutine, runningFadeIn;
    public int fadeInCoRunning, fadeOutCoRunning;
    public AudioClip Win, Lose;
	// Use this for initialization
	void Start () {
        audioCurrent = audioA;
        firstPatternLoaded = false;
        runningCoroutine = false;
        StartCoroutine(pitchAdapt());
    }
	public void startSong()
    {
        if (runningCoroutine||controller.gameOver) return;
        if (audioCurrent.isPlaying)
        {
            StopCoroutine(pitchAdapt());
            StartCoroutine(FadeOut(audioCurrent.GetComponent<AudioSource>()));
        }
        if (audioCurrent.GetInstanceID() == audioA.GetInstanceID()) audioCurrent = audioB;
        else audioCurrent = audioA;
        StartCoroutine(FadeIn(audioCurrent.GetComponent<AudioSource>()));
        
        pitchVariationSemitone = Mathf.RoundToInt(Random.value * (maxPitch - minPitch) + minPitch);
        currentPitchVariation = pitchVariationSemitone;
        audioCurrent.pitch = Mathf.Pow(2, pitchVariationSemitone / 12);
        // set audio track
        if (firstPatternLoaded)
        {
            audioCurrent.clip = audioClips[controller.soundPlaying];
            audioCurrent.Play();
        }
        else
        {
            StartCoroutine(intro());
        }
        swiper.Click = false;
    }
    IEnumerator intro() {
        runningCoroutine = true;
        audioCurrent.clip = startingClip;
        audioCurrent.Play();
        yield return new WaitWhile(() => audioCurrent.time < audioCurrent.clip.length);
        //Debug.Log("fine intro");
        audioCurrent.clip = audioClips[controller.soundPlaying];
        audioCurrent.Play();
        firstPatternLoaded = true;
        audioA.loop = true;
        audioB.loop = true;
        runningCoroutine = false;
    }

    IEnumerator FadeOut(AudioSource audioSource)
    {
        fadeOutCoRunning++;
        do
        {
            audioSource.volume -= 1 / volumeChangeSteps;
            yield return new WaitForSeconds(volumeChangeFrame);
        }
        while ((audioSource.volume > 0)&&(fadeOutCoRunning<2));
        audioSource.Stop();
        if (fadeOutCoRunning > 1) controller.performance = 0;
        fadeOutCoRunning--;
    }
    IEnumerator FadeIn(AudioSource audioSource)
    {
        fadeInCoRunning++;
        do
        {
            audioSource.volume += 1 / volumeChangeSteps;
            yield return new WaitForSeconds(volumeChangeFrame);
        }
        while ((audioSource.volume< 1)&&(fadeInCoRunning<2));
        if (fadeInCoRunning > 1) controller.performance=0;
        fadeInCoRunning--;
    }
    // Update is called once per frame
    void Update () {

        if (swiper.SwipeUp)
        {
            pitchVariationSemitone += Mathf.RoundToInt(Mathf.Atan(Mathf.Abs(swiper.swipeIntensity) / divisor) * 2 / Mathf.PI * maxPitch);
        }
        if (swiper.SwipeDown)
        {
            pitchVariationSemitone += Mathf.RoundToInt(Mathf.Atan(Mathf.Abs(swiper.swipeIntensity) / divisor) * 2 / Mathf.PI * minPitch);
        }
    }
    IEnumerator pitchAdapt()
    {
        do
        {
            pitchError = Mathf.Abs(currentPitchVariation);
            currentPitchVariation = Mathf.MoveTowards(currentPitchVariation, pitchVariationSemitone, 1 / pitchChangeSteps);
            audioCurrent.pitch = Mathf.Pow(2, currentPitchVariation / 12);
            yield return new WaitForSeconds(pitchChangeFrame);
        }
        while (true);
    }
    public void gameOver() {
        StartCoroutine(FadeOut(audioCurrent.GetComponent<AudioSource>()));
        if (audioCurrent.GetInstanceID() == audioA.GetInstanceID()) audioCurrent = audioB;
        else audioCurrent = audioA;
        StartCoroutine(FadeIn(audioCurrent.GetComponent<AudioSource>()));
        if (controller.win) audioCurrent.clip = Win;
        else audioCurrent.clip = Lose;
        audioCurrent.Play();
    }
}
