/****************************************************************************
**  This is a part of ParticleTracer                                       **
**  Copyright (C) 2016  Simon Garnotel                                     **
**                                                                         **
**  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/>.  **
**                                                                         **
** **************************************************************************
**                                                                         **
** Author: Simon Garnotel                                                  **
** Contact: simon.garnotel@gmail.com                                       **
** Date: 06/2016                                                           **
** Version: 1.0                                                            **
****************************************************************************/

#include "header.hpp"

bool CreateProgrammableSource(const string FileName, double **Points, double **Velocities, const unsigned int NPoints, const int NSourcePoints, const double DeltaT){
	//Create Source Points
	vector<double> SourcePointsX, SourcePointsY, SourcePointsZ;
	for (unsigned int i = 0; i <NPoints; i++){
		SourcePointsX.push_back(Points[0][i]);
		SourcePointsY.push_back(Points[1][i]);
		SourcePointsZ.push_back(Points[2][i]);
	}
	
	//Calcualte max velocity
	double MaxVelocityX = abs(Velocities[0][0]);
	double MaxVelocityY = abs(Velocities[1][0]);
	double MaxVelocityZ = abs(Velocities[2][0]);
	for (unsigned int i = 1; i < NPoints; i++){
		if (MaxVelocityX < abs(Velocities[0][i])) MaxVelocityX = abs(Velocities[0][i]);
		if (MaxVelocityY < abs(Velocities[1][i])) MaxVelocityY = abs(Velocities[1][i]);
		if (MaxVelocityZ < abs(Velocities[2][i])) MaxVelocityZ = abs(Velocities[2][i]);
	}
	double MaxVelocity = max(abs(MaxVelocityX), abs(MaxVelocityY));
	MaxVelocity = max(MaxVelocity, abs(MaxVelocityZ));
	
	for (unsigned int i = 0; i < NPoints; i++){
		unsigned int LOCAL__NSourcePoints = NSourcePoints * sqrt(pow(Velocities[0][i], 2) + pow(Velocities[1][i], 2) + pow(Velocities[2][i], 2)) / (MaxVelocity);
		for (unsigned int j = 0; j < LOCAL__NSourcePoints; j++){
			double DeltaX = (double)(j+1)*DeltaT*Velocities[0][i]/(double)LOCAL__NSourcePoints;
			double DeltaY = (double)(j+1)*DeltaT*Velocities[1][i]/(double)LOCAL__NSourcePoints;
			double DeltaZ = (double)(j+1)*DeltaT*Velocities[2][i]/(double)LOCAL__NSourcePoints;
			SourcePointsX.push_back(Points[0][i] + DeltaX);
			SourcePointsY.push_back(Points[1][i] + DeltaY);
			SourcePointsZ.push_back(Points[2][i] + DeltaZ);
		}
	}
	
	long int NTotalPoints = SourcePointsX.size();
	
	//Write ProgrammableSource
	{
		ofstream File(FileName.c_str(), ios::out | ios::trunc);
		if (File){
			File << "# This file is automatically generated" << endl;
			File << "# DO NOT MODIFY" << endl;
			File << "pdo = self.GetPolyDataOutput()" << endl;
			File << "newPts = vtk.vtkPoints()" << endl;
			for (int i = 0; i < NTotalPoints; i++){
				File << "newPts.InsertPoint(";
				File << i;
				File << ", ";
				File << SourcePointsX[i];
				File << ", ";
				File << SourcePointsY[i];
				File << ", ";
				File << SourcePointsZ[i];
				File << ")" << endl;
			}
			File << "pdo.SetPoints(newPts)" << endl;
			File << "aPolyLine = vtk.vtkPolyLine()" << endl;
			File << "aPolyLine.GetPointIds().SetNumberOfIds(";
			File << NTotalPoints;
			File << ")" << endl;
			File << "for i in range(0, ";
			File << NTotalPoints;
			File << "):" << endl;
			File << "   aPolyLine.GetPointIds().SetId(i, i)" << endl;
			File << "pdo.Allocate(1, 1)" << endl;
			File << "pdo.InsertNextCell(aPolyLine.GetCellType(), aPolyLine.GetPointIds())" << endl;
			File.close();
		}
		else{
			cout << "ERROR: CreateProgrammableSource failed!" << endl;
			cout << "File " << FileName << endl;
			return false;
		}
	}
	
	return true;
}



