#include "AudioSource.hpp"
#include "Vector3.hpp"
#include "elements/Transformable.hpp"

float TSE::AudioSource::GetMinDistance()
{
    return minDistance;
}

float TSE::AudioSource::GetMaxDistance()
{
    return maxDistance;
}

bool TSE::AudioSource::GetGlobal()
{
    return global;
}

void TSE::AudioSource::SetGlobal(bool v)
{
    if(global != v)
    {
        auto it = sounds.begin();
        for (int j = 0; j < sounds.size(); j++)
        {
            it->second;
            ma_sound_set_spatialization_enabled(it->second, !v);
            it++;
        }
    }
    global = v;
}

void TSE::AudioSource::SetMinDistance(float v)
{
    minDistance = v;
    auto it = sounds.begin();
    for (int j = 0; j < sounds.size(); j++)
    {
        it->second;
        ma_sound_set_min_distance(it->second, minDistance);
        it++;
    }
}

void TSE::AudioSource::SetMaxDistance(float v)
{
    maxDistance = v;
    auto it = sounds.begin();
    for (int j = 0; j < sounds.size(); j++)
    {
        it->second;
        ma_sound_set_max_distance(it->second, maxDistance);
        it++;
    }
}

void TSE::AudioSource::AddClip(AudioClip *clip)
{
    clips[clip->name] = clip;
    ma_sound* s = clip->GetAudioSound();
    ma_sound_set_spatialization_enabled(s, !global);
    ma_sound_set_attenuation_model(s, ma_attenuation_model_linear);
    ma_sound_set_rolloff(s, 1.0f);
    ma_sound_set_min_distance(s, minDistance);
    ma_sound_set_max_distance(s, maxDistance);
    ma_sound_set_min_gain(s, 0.0f);
    ma_sound_set_max_gain(s, 1.0f);
    sounds[clip->name] = s;
}

void TSE::AudioSource::RemoveClip(std::string name)
{
    if(currentlyPlaying == name) StopPlaying();
    clips[name]->DestroyAudioSound(sounds[name]);
    clips.erase(name);
    sounds.erase(name);
}

void TSE::AudioSource::StartClip(std::string name, bool forceRestart)
{
    if(currentlyPlaying != name){
        StopPlaying();
    }
    else if(forceRestart)
    {
        ma_sound_seek_to_pcm_frame(sounds[name], 0);
    }
    ma_sound_start(sounds[name]);
    currentlyPlaying = name;
}

void TSE::AudioSource::StopPlaying()
{
    if(currentlyPlaying == "") return;
    ma_sound_stop(sounds[currentlyPlaying]);
    ma_sound_seek_to_pcm_frame(sounds[currentlyPlaying], 0);
    currentlyPlaying = "";
}

void TSE::AudioSource::PausePlaying()
{
    if(currentlyPlaying == "") return;
    ma_sound_stop(sounds[currentlyPlaying]);
}

TSE::AudioClip *TSE::AudioSource::GetClipAt(int i)
{
    auto it = clips.begin();
    for (int j = 0; j < i; j++)
    {
        it++;
    }
    return it->second;
}

TSE::AudioSource::~AudioSource()
{
    int count = clips.size();
    for (int i = 0; i < count; i++)
    {
        std::string name = GetClipAt(0)->name;
        RemoveClip(name);
    }
}

void TSE::AudioSource::OnUpdate()
{
    if(!global)
    {
        Vector3 pos = baseObject->GetGlobalPosition();
        ma_sound_set_position(sounds[currentlyPlaying], pos.x, pos.y, -pos.z);
    }
}
