//	Sounds.cpp - Singleton to play sound effects.
//  ----------------------------------------------------------------------------
//	This file is part of 'Die, you Stupid Hurdlers!', a game for Ludum Dare 14.
//	Copyright (C) 2009  Niall Moody
//	
//	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 "Sounds.h"
#include "BackgroundMusic.h"

#include <sstream>
#include <fstream>
#include <iostream>
#include <vorbis/codec.h>

using namespace std;

//------------------------------------------------------------------------------
Sounds& Sounds::getInstance()
{
	static Sounds retval;

	return retval;
}

//------------------------------------------------------------------------------
void Sounds::playSound(SoundType sound)
{
	int i;

	for(i=0;i<NumSounds;++i)
	{
		if(!sounds[i].active)
		{
			sounds[i].data = soundFiles[sound].data;
			sounds[i].size = soundFiles[sound].size;
			sounds[i].index = 0;
			sounds[i].active = true;
			++activeSounds;
			break;
		}
	}
}

//------------------------------------------------------------------------------
void Sounds::getAudio(float *buffer, int numSamples)
{
	int i, j;
	int remainingSounds = activeSounds;

	if(activeSounds == 0)
		return;

	for(j=0;j<NumSounds;++j)
	{
		if(sounds[j].active)
		{
			for(i=0;i<numSamples;++i)
			{
				buffer[(i*2)] += sounds[j].data[sounds[j].index] * 0.25f;
				buffer[(i*2)+1] += sounds[j].data[sounds[j].index] * 0.25f;
				++sounds[j].index;
				if(sounds[j].index >= sounds[j].size)
				{
					sounds[j].active = false;
					break;
				}
			}

			--remainingSounds;
			if(remainingSounds == 0)
				break;
		}
	}
}

//------------------------------------------------------------------------------
Sounds::Sounds():
activeSounds(0)
{
	stringstream tempPath;

	//Connect.
	tempPath << BackgroundMusic::getSoundsPath() << "Birth.ogg";
	loadFile(tempPath.str(), &(soundFiles[Birth]));
	tempPath.str("");

	//Die.
	tempPath << BackgroundMusic::getSoundsPath() << "CapitalistCollision.ogg";
	loadFile(tempPath.str(), &(soundFiles[CapitalistCollision]));
	tempPath.str("");

	//Drop.
	tempPath << BackgroundMusic::getSoundsPath() << "CapitalistDeath.ogg";
	loadFile(tempPath.str(), &(soundFiles[CapitalistDeath]));
	tempPath.str("");

	//Jump.
	tempPath << BackgroundMusic::getSoundsPath() << "Death.ogg";
	loadFile(tempPath.str(), &(soundFiles[Death]));
	tempPath.str("");

	//Lightbox.
	tempPath << BackgroundMusic::getSoundsPath() << "DebilitationWave.ogg";
	loadFile(tempPath.str(), &(soundFiles[DebilitationWave]));
	tempPath.str("");

	//Pickup.
	tempPath << BackgroundMusic::getSoundsPath() << "PoliceCollision.ogg";
	loadFile(tempPath.str(), &(soundFiles[PoliceCollision]));
	tempPath.str("");

	//Pickup.
	tempPath << BackgroundMusic::getSoundsPath() << "TurnRevolutionary.ogg";
	loadFile(tempPath.str(), &(soundFiles[TurnRevolutionary]));
	tempPath.str("");
}

//------------------------------------------------------------------------------
Sounds::~Sounds()
{
	int i;

	for(i=0;i<NumSoundTypes;++i)
		delete [] soundFiles[i].data;
}

//------------------------------------------------------------------------------
void Sounds::loadFile(const string& tempstr, SoundFile *sf)
{
	FILE *file;
	OggVorbis_File vorbisFile;

	int i;
	int result;
	float **tempBuf;
	int currentBitstream = 0;
	unsigned int samplesRead = 0;
	unsigned int length;
	unsigned int runningCount = 0;

	file = fopen(tempstr.c_str(), "rb");
	if(!file)
		cout << "vorbisfile: fopen could not open file: " << tempstr << endl;
	else
	{
		if(ov_open(file, &vorbisFile, NULL, 0) < 0)
			cout << "vorbisfile: Could not open file: " << tempstr << endl;
		else
		{
			if(ov_streams(&vorbisFile) > 0)
			{
				cout << "vorbisfile: Loaded file: " << tempstr << endl;

				length = ov_pcm_total(&vorbisFile, 0);
				sf->size = length;
				sf->data = new float[sf->size];

				while(runningCount < sf->size)
				{
					result = ov_read_float(&vorbisFile,
										   &tempBuf,
										   sf->size,
										   0);
					if(result > 0)
					{
						for(i=0;i<result;++i)
							sf->data[runningCount+i] = tempBuf[0][i];
					}

					runningCount += result;
					if(result == 0)
						break;
				}
			}
			else
			{
				ov_clear(&vorbisFile);
				cout << "vorbisfile: There are no streams in this file?" << endl;
			}
		}
	}
}
