/*
 * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
 *                         UNIVERSITAT POMPEU FABRA
 *
 *
 * 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 2 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include "TestScore.hxx"
#include <cmath>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <cstdlib>
namespace CLAM {

TestScore::TestScore() :
	counter(0),
	numberOfIterations(1000),
	numberOfEventsLoaded(0),
	scoreVector(2, std::vector<float>(6000))
{
	SetFeedForever(false);
}

TestScore::TestScore(std::string filename) :
	counter(0),
	numberOfIterations(1000),
	scoreVector(2, std::vector<float>())
{
	SetFeedForever(false);
	
	isScoreLoaded = LoadScore(filename);
}

TestScore::~TestScore()
{
}

bool TestScore::LoadScore(std::string filename)
{
	std::cout << "TestScore::LoadScore. filename: " << filename << std::endl;

	bool debug = false;
	std::string line;
	std::ifstream myfile (filename.c_str());
	if (!myfile.is_open())
	{
		printf("TestScore: LoadScore; could not open <%s>\n", filename.c_str());
		fflush(stdout);
		return false;
	}
	else
	{
		int rowNumber = 0;
		while (! myfile.eof() )
		{
			getline (myfile, line, '\r');

			if (debug) std::cout << "TestScore::LoadScore. line: " << line << std::endl;

			std::vector<std::string> tokens;
			tokenize(line, tokens);

			if (debug) std::cout << "TestScore::LoadScore. number of tokens: " << tokens.size() << std::endl;

			if (tokens.size() == 0)
				continue;

			for (int columnNumber = 0; columnNumber < tokens.size(); columnNumber++)
			{
				const char* stringToken = tokens.at(columnNumber).c_str();
				float floatToken = (float) std::atof(stringToken);

				scoreVector[columnNumber][rowNumber] =  floatToken;
			}
			rowNumber++;
		}
		myfile.close();
		
		numberOfEventsLoaded = (rowNumber+1);

		if (debug) std::cout << "TestScore::LoadScore. loaded " << numberOfEventsLoaded << " score events." << std::endl;
	}

	return true;
}

void TestScore::tokenize(	const std::string& str,
							std::vector<std::string>& tokens,
							const std::string& delimiters)
{
	// Skip delimiters at beginning.
	std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
	// Find first "non-delimiter".
	std::string::size_type pos     = str.find_first_of(delimiters, lastPos);

	while (std::string::npos != pos || std::string::npos != lastPos)
	{
		// Found a token, add it to the vector.
		tokens.push_back(str.substr(lastPos, pos - lastPos));
		// Skip delimiters.  Note the "not_of"
		lastPos = str.find_first_not_of(delimiters, pos);
		// Find next "non-delimiter"
		pos = str.find_first_of(delimiters, lastPos);
	}
}

bool TestScore::GetControlValues(float& pitch, float& amplitude)
{
	if (isScoreLoaded)
		return NextFrameFromScore(pitch, amplitude);
	else
		return NextFrameAutogenerated(pitch, amplitude);
}

bool TestScore::NextFrameFromScore(float& pitch, float& amplitude)
{
	if ( (counter+1) > (2*numberOfEventsLoaded) )
	{
		if ( !IsFeedForever() )
		{
			return false;
		}
		else
		{
			counter = 0;
			return NextFrameFromScore(pitch, amplitude);
		}
	}
	else
	{
		pitch = scoreVector[0][counter];
		amplitude = scoreVector[1][counter];
		counter = counter + 2;
		return true;
	}
}

bool TestScore::NextFrameAutogenerated(float& pitch, float& amplitude)
{
	if (counter > 1000)
		return false;

	float basePitch = 440.f;
	float baseAmplitude = 0.f;

	float amplitudeOffset;
	float noteOffset;
	double pitchOffset;

	if (counter < 50)
	{
		noteOffset = (float) (counter / 100.);
		amplitudeOffset = (float) (2 * counter / 100.);
	}
	else if (counter > (numberOfIterations-50))
	{
		noteOffset = (float) ( (numberOfIterations-counter) / 100.);
		amplitudeOffset = (float) (2 * (numberOfIterations-counter) / 100.);
	}
	else
	{
		noteOffset = (float) (50. / 100.);
		amplitudeOffset = 1.f;
	}

	pitchOffset = 440.0 * pow(2, noteOffset/12);

	pitch = basePitch + pitchOffset;
	amplitude = baseAmplitude + amplitudeOffset;

	counter++;

	return true;
}

} // end namespace CLAM


