/*Copyright (C) 2010-2020 Duncan Deveaux

This file is part of Hikou no mizu.

Hikou no mizu is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Hikou no mizu is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Hikou no mizu.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "SoundEngine.hpp"

SoundEngine::SoundEngine() : m_loopIx(0), m_volume(100), m_manager(NULL)
{
    
}

void SoundEngine::playSound(const std::string &soundPath)
{
    Sound sound;
    if (loadSound(soundPath, sound))
    {
        m_playingSounds.push_back(sound);
        m_playingSounds.back().play();
    }
}

bool SoundEngine::loopSound(const std::string &soundPath, float period, unsigned int &targetLoopIx)
{
    Sound loopSound;
    if ( loadSound(soundPath, loopSound) )
    {
        //A free index is m_loopIx
        m_loopingSounds.push_back( LoopingSound(loopSound, period, m_loopIx) );
        m_loopingSounds.back().sound.play();
        
        targetLoopIx = m_loopIx;
        
        m_loopIx++;
        return true;
    }
    
    return false;
}

void SoundEngine::stopLoop(unsigned int loopIx)
{
    std::list<LoopingSound>::iterator it = m_loopingSounds.begin();
    
    while (it != m_loopingSounds.end())
    {
        if (it->ix == loopIx)
        {
            it->sound.stop();
            it = m_loopingSounds.erase(it);
        }
        else
            it++;
    }
}

void SoundEngine::update(float frameTime)
{
    //Playing sounds
    std::list<Sound>::iterator it = m_playingSounds.begin();
    
    while (it != m_playingSounds.end())
    {
        if (!it->isPlaying())
            it = m_playingSounds.erase(it);
        else
            it++;
    }
    
    //Looping sounds
    std::list<LoopingSound>::iterator it_loop;
    
    for (it_loop = m_loopingSounds.begin(); it_loop != m_loopingSounds.end(); it_loop++)
        it_loop->update(frameTime);
}

void SoundEngine::setVolume(float volume)
{
    if (volume >= 0)
    {
        m_volume = volume;
        
        //Apply the new volume to current sources
        std::list<Sound>::iterator it;
        for (it = m_playingSounds.begin(); it != m_playingSounds.end(); it++)
            it->setVolume(volume);
        
        std::list<LoopingSound>::iterator it_loop;
        for (it_loop = m_loopingSounds.begin(); it_loop != m_loopingSounds.end(); it_loop++)
            it_loop->sound.setVolume(volume);
    }
}

float SoundEngine::getVolume() const
{
    return m_volume;
}

void SoundEngine::setManager(SoundBufferManager &manager)
{
    m_manager = &manager;
}

const SoundBufferManager &SoundEngine::getManager() const
{
    return *m_manager;
}

bool SoundEngine::loadSound(const std::string &soundPath, Sound &target)
{
    SoundBuffer *buffer = NULL;
    if (m_manager->getSoundBuffer(soundPath, buffer))
    {
        Sound sound;
        sound.setBuffer((*buffer));
        sound.setVolume(m_volume);
        
        target = sound;
        return true;
    }
    
    return false;
}
