#include "sound_effects.hpp"

#include "sound.hpp"

#include "util.hpp"

namespace sound {
    void SoundEffects::addSoundHandleForObject(game::Object *obj, SoundHandle *handle)
    {
        std::cout<<"add sound for object: " << obj->id << std::endl;
        auto pair = std::pair<size_t, SoundHandle*>(obj->id, handle);
        m_mapObjectToSoundHandle.insert(pair);
    }


    void SoundEffects::fadeOutSoundHandlesForObject(game::Object *obj, float fadeOutTime)
    {
        std::cout<<"deleting sounds for object: " << obj->id << std::endl;
        std::multimap<size_t, SoundHandle*>::iterator it;
        for (it = m_mapObjectToSoundHandle.find(obj->id); it != m_mapObjectToSoundHandle.end(); it++) {
            std::cout<<"sound #" << it->second->uid << " / " << it->second->name << std::endl;
            fadeOut(it->second, fadeOutTime);
        }

        size_t numRemoved = m_mapObjectToSoundHandle.erase(obj->id);
        std::cout<<"removed total sounds: " << numRemoved << std::endl;
    }

    void SoundEffects::advance(float dt, const std::list<game::StateUpdateEvent*> &updates)
    {
        (void) dt;

        for (const game::StateUpdateEvent *evt : updates) {
            auto type  = evt->eventType();
            auto cycle = evt->lifeCycle();
            if (type == game::EventType::Missile) {
                if (cycle == game::LifeCycle::Create) {
                    SoundHandle *handle = playFrequency(880.0, 0.1);
                    if (handle == nullptr) {
                        continue;
                    }
                    fadeIn(handle);
                    handle->name = "missile-fly-sound_fade-in";

                    addSoundHandleForObject(evt->object(), handle);

                } else if (cycle == game::LifeCycle::Destroy) {
                    fadeOutSoundHandlesForObject(evt->object());
                }
            } else if (type == game::EventType::Explosion) {
#if 1
                if (cycle == game::LifeCycle::Create) {
                    SoundHandle *handle = playSound(SoundBrownianNoise, 0.4);
                    if (handle == nullptr) {
                        continue;
                    }
                    configureEnvelope(handle, 0.2, 0.0, 2.0);

                    // add big *boom* sound too
                    handle = playFrequency(200.0, 0.5);
                    if (handle == nullptr) {
                        continue;
                    }
                    configureEnvelope(handle, 0.1, 0.0, 1.0);
                }
#endif
            }
        }
    }

    void SoundEffects::fadeIn(SoundHandle *handle, float fadeInTime)
    {
        // assume sound has just started
        configureEnvelope(handle, fadeInTime, 1000000.0, 0.0);
    }

    void SoundEffects::fadeOut(SoundHandle *handle, float fadeOutTime)
    {
        // reset time so it imediately starts to fade out.
        configureEnvelope(handle, 0.0, 0.0, fadeOutTime);
        handle->time = 0.0;
    }
}
