#include <iostream>
#include <fstream>
#include <sstream>
#include <math.h>
#include <string>
using namespace std;

//-----SUBFUNCTION TO CREATE FILENAMES-----
string filenamegenerator(int temp_places, int temp_input_number, string temp_prefix){
	stringstream temp_Filename;
	stringstream temp;
	int temp_used_places;
	//Funktion zum Zählen der Stellen eines Integers
	temp << temp_input_number;
	temp_used_places=(temp.str()).length();//Zaehlen der Stellen
//	temp.str(""); //stringstream leeren
	//Funktion zum Auffuellen des Dateinamens mit Nullen bis Anzahl temp_places erreicht ist.
	//Bsp: aus 50 wird 0050, wenn temp_places=4 und temp_input_number=50
	temp_Filename << temp_prefix;
	for (int s=1; s<=temp_places-temp_used_places; s=s+1)
		{
		temp_Filename << "0";
		}
	temp_Filename << temp_input_number;//Hinzufuegen des Prefixes
	return temp_Filename.str();
}

//-----MAIN FUNCTION-----
int main () {
	double A;
	double E;
	double T_start;
	double R = 8.3144621;
	int savesteps;
	string prefix;
    int amount_of_stars;

	//------------------------------------------------------------

	cout << "***************************************************************\n"
            "* AddingArrhenius 1.1beta3: ******************* 2012,2014 KIT *\n"
            "***************************************************************\n"
            "* Application to calculate the Arrhenius from the Temperature *\n"
            "***************************************************************\n\n";
	cout << "A = ? (/s) \n";
	cin >> A;
	cout << "\ndE = ? (J/mol) \n";
	cin >> E;
	cout << "\nThe prefix of the Encas file (prefix.encas). (string) \n";
	cin >> prefix;
	cout << "\nStart Temperature of the Step Zero (Initialization Value in Fluent). (string) \n";
	cin >> T_start;
	cout << "\n";
	

	//------------------------------------------------------------

    stringstream encasFilename;
    encasFilename << prefix << ".encas";
    ifstream encasFile(encasFilename.str().c_str());
    string encasLine;
	
    double* timevalues; //Array for timevalues obtained from *.encas-file
    string filename_line;
	string filename_prefix;
    string filename_suffix;
    int filename_start_number;
    int number_of_steps;
    int amount=0;
    int k=0;
	int current_step;
	
    while (encasFile.good())
        {
		getline (encasFile, encasLine);

		if (encasLine.substr(0,35)== "scalar per element:  1  temperature")//gets line with filename and amount of stars
            {
            //gets number of timesteps and converts them into an int, "atoi: if the converted value would be out of the range of values representable by an int, it causes undefined behaviour."
            filename_line=encasLine.substr(50, encasLine.length());
            amount_of_stars=filename_line.find_last_of("*")-filename_line.find_first_of("*")+1;//gets number of stars
            filename_prefix=filename_line.substr(0, filename_line.find_first_of("*"));//gets filename_prefix of result files
            filename_suffix=filename_line.substr(filename_line.find_last_of(".")+1, filename_line.length()-filename_line.find_last_of("."));//gets filename suffix of result files
            }

		if ((encasLine.substr(0,22)== "filename start number:"))//gets line with filename start number
            {
            //gets number of timesteps and converts them into an int, "atoi: if the converted value would be out of the range of values representable by an int, it causes undefined behaviour."
            filename_start_number=atoi((encasLine.substr(28, encasLine.length()-28)).c_str());
            }

   		if ((encasLine.substr(0,19)== "filename increment:"))//gets line with filename increment
            {
            //gets number of timesteps and converts them into an int, "atoi: if the converted value would be out of the range of values representable by an int, it causes undefined behaviour."
            savesteps=atoi((encasLine.substr(28, encasLine.length()-28)).c_str());
            }

        if ((encasLine.substr(0,17)== "number of steps: ")&&(encasLine.substr(0,18)!= "number of steps:  "))//gets first line with number of steps
            {
            //gets number of steps and converts them into an int, "atoi: if the converted value would be out of the range of values representable by an int, it causes undefined behavior."
            number_of_steps=atoi((encasLine.substr(17, encasLine.length()-17)).c_str());
            timevalues = (double*)malloc(number_of_steps*sizeof(double));//allocate memory for array
            }

        if ((encasLine.substr(0,12)== "time values:")&&(amount==0))//gets line with time values
            {
            amount=1;//Increase variable to go only once in this If condition
            while (encasLine.substr(0,9)!="time set:") //tokenize lines until line time set is found
                {
               //function to tokenize adapted from http://www.cplusplus.com/faq/sequences/strings/split/#string-find_first_of
                string delimiters = " ";
                size_t current;
                size_t next = -1;
                if (encasLine.substr(0,14)== "time values:  ")//for the line with "time values:" in it, use substring
                    {
                    do  {
                        next = (encasLine.substr(14)).find_first_not_of( delimiters, next + 1 );
                        if (next == string::npos) break;
                        next -= 1;
                        current = next + 1;
                        next = (encasLine.substr(14)).find_first_of(delimiters, current);
                        timevalues[k]=atof(((encasLine.substr(14)).substr(current, next - current)).c_str());
                        k=k+1;
                        } while (next != string::npos);
                    }
                else	//for all following lines with timesteps without the description "time values:" in it, use line from file directly
                    {
                    do  {
                        next = encasLine.find_first_not_of( delimiters, next + 1 );
                        if (next == string::npos) break;
                        next -= 1;
                        current = next + 1;
                        next = encasLine.find_first_of(delimiters, current);
                        timevalues[k]=atof((encasLine.substr(current, next - current)).c_str());
                        k=k+1;
                        } while (next != string::npos);            
                    }
                getline (encasFile, encasLine);
                }
            }
        }

	//------------------------------------------------------------

	for (int i = 0; i < number_of_steps; i = i + 1) {
		current_step=(savesteps*(i)+filename_start_number);
        cout << "Current File: " << current_step << "/" << savesteps*(number_of_steps-1)+filename_start_number << endl;

        //generating the names of the needed files:
        stringstream currentFilename;//Attention: Defined in for-loop. If defined outside, variable must be cleared in the end of the for-loop!
        stringstream prevFilename;//Attention: Defined in for-loop. If defined outside, variable must be cleared in the end of the for-loop!
        currentFilename << filenamegenerator(amount_of_stars, current_step, filename_prefix);
        if (current_step != filename_start_number) {
           prevFilename << filenamegenerator(amount_of_stars, current_step-savesteps, filename_prefix);
        }
		
	//---------------------------------------------------------
	//Open the needed files for reading:
		
		stringstream currentTempFilename;
		currentTempFilename << currentFilename.str() << ".scl1";
		ifstream currentTempFile (currentTempFilename.str().c_str());
		if (!currentTempFile.is_open()) {
			cout << "Step " << current_step << ": Error while reading currentTempFile " << currentTempFilename.str() << endl;
			cin.get();
		}

		stringstream prevTempFilename;
		prevTempFilename << prevFilename.str() << ".scl1";
		ifstream prevTempFile (prevTempFilename.str().c_str());
		if (!prevTempFile.is_open() && current_step != savesteps) {
			cout << "Step " << current_step << ": Error while reading prevTempFile " << prevTempFilename.str() << endl;
			cin.get();
		}
		
		stringstream prevArrFilename;
		prevArrFilename << prevFilename.str() << ".arr";
		ifstream prevArrFile (prevArrFilename.str().c_str());
		if (!prevArrFile.is_open() && current_step != savesteps) {
			cout << "Step " << current_step << ": Error while reading prevArrFile " << prevArrFilename.str() << endl;
			cin.get();
		}

	//----------------------------------------------------------
	// open (and create) file for arrhenius factor:
		
		stringstream currentArrFilename;
		currentArrFilename << currentFilename.str() << ".arr";
		
//FILE* fout;
//fout=fopen("bla2.txt", "w");

		ofstream currentArrFile;
		currentArrFile.open (currentArrFilename.str().c_str());
		
		if (!currentArrFile.is_open()) {
			cout << "Step " << current_step << ": Error while creating cuurentArrFile " << currentArrFilename.str() << endl;
			cin.get();
		}
		//------------------------------------------------------------
		//write text and values into file for arrhenius factor:
		
		string currentTempLine;
		string prevTempLine;
		string prevArrLine;
		double currentTemp;
		double prevTemp;
		double prevArr;
		double currentArr;
	
//		ios::sync_with_stdio(false);//no speed increase measured
		while (getline(currentTempFile, currentTempLine)) {
			//Hole nächste Linie aus dem aktuellen scl1-file
			//getline (currentTempFile, currentTempLine);
			//Wenn nicht erste Datei
			if (current_step != savesteps)
                {
				getline (prevArrFile, prevArrLine);
				getline (prevTempFile, prevTempLine);
    			}
			//Tausche am Beginn Static Temperature gegen Arrhenius und kopiere die anderen Zeilen am Beginn der aktuellen scl1-Datei
			if (currentTempLine[1] != '0' && currentTempLine[1] != '1' && currentTempLine[1] != '2' && currentTempLine[1] != '3' && currentTempLine[1] != '4' && currentTempLine[1] != '5' && currentTempLine[1] != '6' && currentTempLine[1] != '7' && currentTempLine[1] != '8' && currentTempLine[1] != '9')
                {
				if (currentTempLine == "Static Temperature")
                    {
					currentArrFile << "Arrhenius" << endl;
    				}
				else
                    {
					currentArrFile << currentTempLine << endl;
    				}
    			}
			//Berechne aus den Temperaturwerten den Arrhenius
			else
                {
				currentTemp = atof(currentTempLine.c_str());
				if (current_step != savesteps)
                    {
					prevArr = atof(prevArrLine.c_str());
					prevTemp = atof(prevTempLine.c_str());
					currentArr = prevArr + (timevalues[i]-timevalues[i-1])*A*0.5*( exp(-E/(currentTemp*R)) + exp(-E/(prevTemp*R)) );
    				}
				else
                    {
					currentArr = timevalues[i]*A*0.5*( exp(-E/(currentTemp*R)) + exp(-E/(T_start*R)) );
    				}
				currentArrFile << " " << currentArr << endl;//SLOWEST OPERATION IN APPLICATION, TAKES 80% of PROCESSING TIME
                //currentArrFile << ' ' << currentArr << '\n';
                //fprintf(fout, " %g\n", currentArr);// viel schneller aber leider nicht korrekt, da 300 Zeilen einfach weggelassen wurden, mit fclose nur noch 100 Linien
    			}
		}
		//---------------------------------------------------------------
		//closing Files:
        //fflush(fout);
		//fclose(fout);
		currentTempFile.close();
		prevTempFile.close();
		currentArrFile.close();
		prevArrFile.close();
	}
	//---------------------------------------------------------------
	//changing the information file of encas:

    encasFile.clear();//reset error flags, to start reading the encas file again
    encasFile.seekg(0, encasFile.beg);//reset pointer position to beginning of encas input file, to start reading the encas file again
	
	stringstream newName;
	newName << prefix << "WithArrhenius.encas";
	ofstream newEncas;
	newEncas.open(newName.str().c_str());
	
	while (encasFile.good())
        {
		getline (encasFile, encasLine);
		if (encasLine != "VARIABLE")
            {
			newEncas << encasLine << endl;
            }
		else
            {
			newEncas << "VARIABLE" << endl << "scalar per element:  1  arrhenius                 " << filename_prefix;
			for (int t=1; t<=amount_of_stars; t=t+1)
        		{
        		newEncas << "*";
        		}
            newEncas << ".arr" << endl;
            }
        }
	encasFile.close();
	newEncas.close();

    cout << endl << "Calculation Done" << endl;
    system ("pause");
	return 0;
}




