//	PitchFactory.cpp - Singleton holding all the available pitch sets.
//  ----------------------------------------------------------------------------
//	This file is part of 'GameTemplate', template code for a game.
//	Copyright (C) 2011  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 "PitchFactory.h"
#include "FilePath.h"
#include "UTF8File.h"
#include "Random.h"

#include <fstream>
#include <sstream>
#include <cassert>

using namespace std;

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

	return retval;
}

//------------------------------------------------------------------------------
void PitchFactory::loadPitches()
{
	int i, j;
	FilePath pitchDir = FilePath::getDataFilesDir().getChild(L"pitches");
	const int numPitchFiles = pitchDir.getNumChildren();

	if(pitchDir.exists())
	{
		for(i=0;i<numPitchFiles;++i)
		{
			FilePath pitchFile = pitchDir.getChild(i);

			if(pitchFile.exists())
			{
				if(pitchFile.getExtension() == L"txt")
				{
					UTF8File phil(pitchFile);

					if(!phil.getFail())
					{
						float tempf;
						std::wstring tempstr;
						array<float, 8> pitches;
						std::wstringstream tempstr2;

						j = 0;
						while(!phil.readLine(tempstr))
						{
							assert(j < 8);

							tempstr2.str(tempstr);
							tempstr2 >> tempf;

							pitches[j] = tempf;
							tempstr2.clear();

							++j;
						}
						assert(j == 8);

						pitchSets.push_back(pitches);
					}
				}
			}
		}
		lastSet = (int)(Random::getGlobal().getRandomFloat() * ((float)pitchSets.size()-0.001f));
	}
}

//------------------------------------------------------------------------------
vector<float> PitchFactory::getPitches(int numPitches)
{
	int i, j;
	//float tempf;
	vector<float> retval;
	//int upperLimit, lowerLimit;

	assert(pitchSets.size() > 0);

	//Select a new pitch set, being careful not to get into an infinite loop if
	//there's only 1 set available.
	if(pitchSets.size() != 1)
	{
		int tempSet = lastSet;

		while(tempSet == lastSet)
			tempSet = (int)(Random::getGlobal().getRandomFloat() * ((float)pitchSets.size()-0.001f));

		lastSet = tempSet;
	}
	else if(lastSet != 0) //Just in case.
		lastSet = 0;

	//Add pitches from the selected pitch set to retval.
	i = -1;
	j = numPitches;
	/*//Original pitch selection algorithm (random).
	while((int)retval.size() < numPitches)
	{
		upperLimit = 8-j;
		lowerLimit = i+1;

		tempf = (float)(upperLimit-lowerLimit) + 0.99f;

		i = (int)(Random::getGlobal().getRandomFloat() * tempf);
		i += lowerLimit;
		--j;

		retval.push_back(pitchSets[lastSet][i]);
	}*/

	//Select adjacent pitches.
	i = (int)(Random::getGlobal().getRandomFloat() * ((float)(8-numPitches) * 0.99f));
	for(j=0;j<numPitches;++j,++i)
		retval.push_back(pitchSets[lastSet][i]);

	return retval;
}

//------------------------------------------------------------------------------
PitchFactory::PitchFactory():
lastSet(0)
{
	loadPitches();
}

//------------------------------------------------------------------------------
PitchFactory::~PitchFactory()
{

}
