/*
  Copyright (C) 2010-2011  Charles Pence <charles@charlespence.net>
  Copyright (C) 1996-1997  Id Software, Inc.

  This program 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.

  This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "../pch.h"
#include "../quakedef.h"
#include <physfs.h>
#include "../filesystem/filesystem.h"
#include "../filesystem/physfsrwops.h"
#include "sample.h"

namespace sound
{

Sample::SampleList Sample::samples_;
boost::mutex Sample::sample_lock_;


unsigned Sample::Load(const std::string &samplename)
{
    // Look to see if the sample's already been loaded
    {
        boost::mutex::scoped_lock lock(sample_lock_);
        for (size_t i = 0 ; i < samples_.size() ; i++)
        {
            if (samples_[i]->name_ == samplename)
                return i;
        }
    }
    
    // Sample names are passed without the folder
    std::string filename("sound/");
    filename += samplename;
    
    // Open the file
    SDL_RWops *rwops = PHYSFSRWOPS_openRead(filename.c_str());
    if (!rwops)
    {
        Con_Printf("Sample::Load: Cannot open %s\n", filename.c_str());
        return (unsigned)-1;
    }
    
    Mix_Chunk *chunk = Mix_LoadWAV_RW(rwops, 1);
    if (!chunk)
    {
        Con_Printf("Sample::Load: Cannot read %s\n", filename.c_str());
        return false;
    }
    
    // Get a new sample
    Pointer s(new Sample);
    s->chunk_ = chunk;
    s->name_ = samplename;
    
    // Load the loop file and set the looping position
    if (!loops_loaded_)
        LoadLoopFile();
    
    if (!loops_.count(filename))
        s->loop_position_ = -1;
    else
        s->loop_position_ = loops_[filename];
    
    // Add it to the list and return the index
    boost::mutex::scoped_lock lock(sample_lock_);
    
    unsigned idx = samples_.size();
    samples_.push_back(s);
    return idx;
}

Sample::Pointer Sample::Get(unsigned index)
{
    boost::mutex::scoped_lock lock(sample_lock_);
    
    if (index >= samples_.size())
        return Pointer();
    
    return samples_[index];
}



bool Sample::loops_loaded_ = false;
boost::unordered_map<std::string, int> Sample::loops_;

void Sample::LoadLoopFile()
{
    // Grab the lock so only one thread will try to write to the
    // loops_[] variable at one time.
    boost::mutex::scoped_lock lock(sample_lock_);
    
    File fp;
    if (fp.OpenRead("sound.loops"))
    {
        // File format: <filename> <loop position>\n
        while (!fp.eof())
        {
            std::string buf = fp.GetLine();
            
            size_t off = buf.find_first_of(' ');
            if (off == std::string::npos)
                continue;
            
            std::string filename(buf, 0, off);
            std::string pos_str(buf, off + 1);
            
            int pos = Util::lexical_cast<int>(pos_str);
            
            loops_[filename] = pos;
        }
    }
    
    // Only try to load this once, even if the file doesn't exist
    loops_loaded_ = true;
}

}