//t ist die Variable die von 0...1 läuft - muss woanders mit der Zeit skaliert werden!!!

#include "spline.h"

Spline::Spline()
{

}



Spline::~Spline()
{}



void Spline::calculateTangentPoints()
{
	//iterate over all controlpoints to get the tangent points
	//Ti = 0.5 * ( P i+1 - Pi-1 )
	//der erste und der letzte Punkt der Kontrollpunkte wird nie durchfahren.
	//also Ti-1 für Pi

	std::vector<glm::vec3>::iterator it = controlpointseye.begin();
	std::vector<glm::vec3>::iterator it2 = controlpointseye.begin();
	it++;
	it++;

	for(; it != controlpointseye.end(); it++, it2++)
	{
		glm::vec3 tmpplus = glm::vec3((*it).x, (*it).y, (*it).z);
		glm::vec3 tmpminus = glm::vec3((*it2).x, (*it2).y, (*it2).z);
	
		glm::vec3 tangent = tmpplus - tmpminus;
		tangent.x = 0.5f * tangent.x;
		tangent.y = 0.5f * tangent.y;
		tangent.z = 0.5f * tangent.z;
		tangentpointseye.push_back(tangent);
	}

	std::vector<glm::vec3>::iterator itcenter = controlpointscenter.begin();
	std::vector<glm::vec3>::iterator itcenter2 = controlpointscenter.begin();
	itcenter++;
	itcenter++;
	for(; itcenter!= controlpointscenter.end(); itcenter++, itcenter2++)
	{
		glm::vec3 tmpplus = glm::vec3((*itcenter).x, (*itcenter).y, (*itcenter).z);
		glm::vec3 tmpminus = glm::vec3((*itcenter2).x, (*itcenter2).y, (*itcenter2).z);

		glm::vec3 tangent = tmpplus - tmpminus;
		tangent.x = 0.5f * tangent.x;
		tangent.y = 0.5f * tangent.y;
		tangent.z = 0.5f * tangent.z;
		tangentpointscenter.push_back(tangent);
	}


}


void Spline::calculateFireTangentPoints()
{
	//iterate over all controlpoints to get the tangent points
	//Ti = 0.5 * ( P i+1 - Pi-1 )
	//der erste und der letzte Punkt der Kontrollpunkte wird nie durchfahren.
	//also Ti-1 für Pi

	std::vector<glm::vec3>::iterator it = controlpointseye.begin();
	std::vector<glm::vec3>::iterator it2 = controlpointseye.begin();
	it++;
	it++;

	for(; it != controlpointseye.end(); it++, it2++)
	{
		glm::vec3 tmpplus = glm::vec3((*it).x, (*it).y, (*it).z);
		glm::vec3 tmpminus = glm::vec3((*it2).x, (*it2).y, (*it2).z);
	
		glm::vec3 tangent = tmpplus - tmpminus;
		tangent.x = 0.5f * tangent.x;
		tangent.y = 0.5f * tangent.y;
		tangent.z = 0.5f * tangent.z;
		tangentpointseye.push_back(tangent);
	}


}

void Spline::addEyeControl(glm::vec3 &point)
{
	controlpointseye.push_back(point);
}

void Spline::addCenterControl(glm::vec3 &point)
{
	controlpointscenter.push_back(point);
}


glm::vec3 Spline::getInterpolPoint(float t, glm::vec3 &p1, glm::vec3 &t1, glm::vec3 &p2, glm::vec3 &t2)
{
	//t ist die Variable die von 0...1 läuft - muss woanders mit der Zeit skaliert werden!!!

	//Calculate the basis functions
	float h1 = 2 * glm::pow(t, 3.0f) - 3 *  glm::pow(t, 2.0f) + 1;
	float h2 = -2 * glm::pow(t, 3.0f) + 3 * glm::pow(t, 2.0f);
	float h3 = glm::pow(t, 3.0f) - 2 * glm::pow(t, 2.0f) + t;
	float h4 = glm::pow(t, 3.0f) - glm::pow(t, 2.0f);

	//get the new vector
	glm::vec3 point = h1*p1 + h2*p2 + h3*t1 + h4*t2;
	return point;
}


bool Spline::load_cam_positions(char* filepath)
{
	FILE **file = new FILE*[1];
	char line[100];
	std::string lineString;
	std::string subStr1;
	std::string subStr2;
	std::string subStr3;

	int ind1 = 0;
	int ind2 = 0;
	int ind3 = 0;

	float x,y,z;
	x = y = z = 0.0f;

	int cnt = 0;

	//open the file
	fopen_s(file, filepath, "rb");

	while(fgets(line, 100, *file))
	{
		lineString = std::string(line);	//get one line of the file

		//case distinction
		if(lineString[0] == 'e')
		{
			//case cam_eye information
			glm::vec3 tmp = glm::vec3(0.0f, 0.0f, 0.0f);
		
			//e 1/2/3#
			ind1 = lineString.find_first_of(' ', 2);
			subStr1 = lineString.substr(2, ind1-2);
			//1#2/3
			ind2 = subStr1.find_first_of('/');
			subStr2 = subStr1.substr(0, ind2);
			tmp.x = StringToFloat(subStr2, 1);

			//1/2#3
			ind3 = subStr1.find_first_of('/', ind2+1);
			subStr3 = subStr1.substr(ind2+1, ind3 - ind2 - 1);
			tmp.y = StringToFloat(subStr3, 1);

			subStr3 = subStr1.substr(ind3 + 1);
			tmp.z = StringToFloat(subStr3, 1);
		
			controlpointseye.push_back(tmp);
		}
		else if(lineString[0] == 'c')
		{
			//case cam_center information
			glm::vec3 tmp = glm::vec3(0.0f, 0.0f, 0.0f);
		
			//e 1/2/3#
			ind1 = lineString.find_first_of(' ', 2);
			subStr1 = lineString.substr(2, ind1-2);
			//1#2/3
			ind2 = subStr1.find_first_of('/');
			subStr2 = subStr1.substr(0, ind2);
			tmp.x = StringToFloat(subStr2, 1);

			//1/2#3
			ind3 = subStr1.find_first_of('/', ind2+1);
			subStr3 = subStr1.substr(ind2+1, ind3 - ind2 - 1);
			tmp.y = StringToFloat(subStr3, 1);

			subStr3 = subStr1.substr(ind3 + 1);
			tmp.z = StringToFloat(subStr3, 1);
		
			controlpointscenter.push_back(tmp);
		}
	
	}//end of while(fgets(line, 100, *file))

	//debuginformation
	//std::cout << "debug eyesize: " <<controlpointseye.size() << endl;
	//std::cout << "debug centersize: " <<controlpointscenter.size() << endl;

	//std::vector<glm::vec3>::iterator it = controlpointseye.begin();
	//std::vector<glm::vec3>::iterator it2 = controlpointscenter.begin();
	//for(; it != controlpointseye.end(); it++, it2++)
	//{
	//	cout << "e " << (*it).x << "/" << (*it).y << "/" << (*it).z << endl;
	//	cout << "c " << (*it2).x << "/" << (*it2).y << "/" << (*it2).z << endl;
	//}


	//calculate the tangent points
	calculateTangentPoints();
	
	////debuginformation
	//std::cout << "debug tangeyesize: " << tangentpointseye.size() << endl;
	//std::cout << "debug tangecentersize: " << tangentpointscenter.size() << endl;
	//
	//std::vector<glm::vec3>::iterator it3 = tangentpointseye.begin();
	//std::vector<glm::vec3>::iterator it4 = tangentpointscenter.begin();
	//for(; it3 != tangentpointseye.end(); it3++, it4++)
	//{
	//	cout << "e " << (*it3).x << "/" << (*it3).y << "/" << (*it3).z << endl;
	//	cout << "c " << (*it4).x << "/" << (*it4).y << "/" << (*it4).z << endl;
	//}

	return true;
}


bool Spline::load_firecam_positions(char* filepath)
{
	FILE **file = new FILE*[1];
	char line[100];
	std::string lineString;
	std::string subStr1;
	std::string subStr2;
	std::string subStr3;

	int ind1 = 0;
	int ind2 = 0;
	int ind3 = 0;

	float x,y,z;
	x = y = z = 0.0f;

	int cnt = 0;

	//open the file
	fopen_s(file, filepath, "rb");

	while(fgets(line, 100, *file))
	{
		lineString = std::string(line);	//get one line of the file

		//case distinction
		if(lineString[0] == 'e')
		{
			//case cam_eye information
			glm::vec3 tmp = glm::vec3(0.0f, 0.0f, 0.0f);
		
			//e 1/2/3#
			ind1 = lineString.find_first_of(' ', 2);
			subStr1 = lineString.substr(2, ind1-2);
			//1#2/3
			ind2 = subStr1.find_first_of('/');
			subStr2 = subStr1.substr(0, ind2);
			tmp.x = StringToFloat(subStr2, 1);

			//1/2#3
			ind3 = subStr1.find_first_of('/', ind2+1);
			subStr3 = subStr1.substr(ind2+1, ind3 - ind2 - 1);
			tmp.y = StringToFloat(subStr3, 1);

			subStr3 = subStr1.substr(ind3 + 1);
			tmp.z = StringToFloat(subStr3, 1);
		
			controlpointseye.push_back(tmp);
		}
	
	}//end of while(fgets(line, 100, *file))

	//debuginformation
	//std::cout << "debug eyesize: " <<controlpointseye.size() << endl;
	//std::cout << "debug centersize: " <<controlpointscenter.size() << endl;

	//std::vector<glm::vec3>::iterator it = controlpointseye.begin();
	//std::vector<glm::vec3>::iterator it2 = controlpointscenter.begin();
	//for(; it != controlpointseye.end(); it++, it2++)
	//{
	//	cout << "e " << (*it).x << "/" << (*it).y << "/" << (*it).z << endl;
	//	cout << "c " << (*it2).x << "/" << (*it2).y << "/" << (*it2).z << endl;
	//}


	//calculate the tangent points
	calculateFireTangentPoints();
	
	////debuginformation
	//std::cout << "debug tangeyesize: " << tangentpointseye.size() << endl;
	//std::cout << "debug tangecentersize: " << tangentpointscenter.size() << endl;
	//
	//std::vector<glm::vec3>::iterator it3 = tangentpointseye.begin();
	//std::vector<glm::vec3>::iterator it4 = tangentpointscenter.begin();
	//for(; it3 != tangentpointseye.end(); it3++, it4++)
	//{
	//	cout << "e " << (*it3).x << "/" << (*it3).y << "/" << (*it3).z << endl;
	//	cout << "c " << (*it4).x << "/" << (*it4).y << "/" << (*it4).z << endl;
	//}

	return true;
}

/*
 * Cast a string to a float
 * string& str_input - string input
 * float default_value - default value for error security issues
 */
float Spline::StringToFloat(const std::string& str_input, const float default_value)
{
  std::stringstream s_str(str_input);
  float value = default_value;
  //now cast it
  if (!(s_str>>value))
  { //error during conversion -> return given default value
    return default_value;
  }
  return value;
}