#include "CSVreaderModule.h"
#include "file_util.h"
#include <string>
#include <string.h>
#include <iostream>

#define STRINGLENGTH 5000

/*
void CSV_Reader :: initialize_csvreader(char* filepath_read, unsigned int num_of_datasets, unsigned int* list_of_datasets, unsigned int start_row) {
	//fpointer_read = fopen(filepath_read, "r");
	fopen_s(&fpointer_read, filepath_read, "r");

	this->num_of_datasets = num_of_datasets;
	//TODO: sort.. falls es nicht in aufsteigender folge kommt
	for(unsigned int d_ix=0; d_ix<num_of_datasets; d_ix++) {
		this->list_of_datasets[d_ix] = list_of_datasets[d_ix];
	}

	row = 1;
	this->start_row = start_row;
}
*/

 void CSVreaderModule :: initialize_csvreader(FILE* fpointer, unsigned int column, unsigned int start_row) {
	//fpointer_read = fopen(filepath_read, "r");
	
	//TODO: file ponter schon aus CSV-Reader Creator Funktion �bergeben.. dann kann man n�mlich ausgeben, wenn da was nicht erstellt werden kann
	//bool file_opened = fopen_s(&fpointer_read, filepath_read, "r");
	//TODO: etwas mit flag

	this->fpointer = fpointer;
	this->row = 1;
	this->column = column;
	this->start_row = start_row;
	
	flag_csv_reader_configured = true;
}


/*
CSV_Reader :: CSV_Reader(char* filepath_read, unsigned int num_of_data_sets, unsigned int* list_of_datasets, unsigned int start_row) {
	set_name(NO_NAME);
	initialize_csvreader(filepath_read, num_of_data_sets, list_of_datasets, start_row);
}

CSV_Reader :: CSV_Reader(char* name, char* filepath_read, unsigned int num_of_data_sets, unsigned int* list_of_datasets, unsigned int start_row) {
	set_name(name);
	initialize_csvreader(filepath_read, num_of_data_sets, list_of_datasets, start_row);
}
*/

CSVreaderModule :: CSVreaderModule() {
	set_name(NO_NAME);
	flag_csv_reader_configured = false;
}

CSVreaderModule :: CSVreaderModule(char* name) {
	set_name(name);
	flag_csv_reader_configured = false;
}

CSVreaderModule :: CSVreaderModule(FILE* fpointer, unsigned int column, unsigned int start_row) {
	set_name(NO_NAME);
	
	if(fpointer) {
		initialize_csvreader(fpointer, column, start_row);
	}
	else {
		flag_csv_reader_configured = false;
	}
}

CSVreaderModule :: CSVreaderModule(char* name, FILE* fpointer, unsigned int column, unsigned int start_row) {
	set_name(name);

	if(fpointer) {
		initialize_csvreader(fpointer, column, start_row);
	}
	else {
		flag_csv_reader_configured = false;
	}
}
/*
CSV_Reader :: CSV_Reader(char* name, char* filepath_read, int column, int start_row) {

}
*/



//XXX: Wird nicht mehr benutzt
//TODO: �berarbeiten nach folgendem Beispiel https://msdn.microsoft.com/en-us/library/ftsafwz3.aspx
bool CSVreaderModule :: read_one_row() {
	if(fpointer)
	{ 
        char readrow[STRINGLENGTH] = "", electedfield[STRINGLENGTH] = ""; 

		//TODO: move following for-loop to "initialize_csvreader(...)
		for(;row<start_row; row++) {

			if(!fgets(readrow, STRINGLENGTH, fpointer))
				return false;
		}

		if(fgets (readrow, STRINGLENGTH, fpointer))
		{
			char *ptr, *next_ptr;
			//TODO: make delimiter configurable!
			#ifdef WINDOWS_OS
				ptr = strtok_s(readrow, ",;", &next_ptr); //windows version
			#elif !WINDOWS_OS
				ptr = strtok_r(readrow, ",;", &next_ptr);
			#endif 			

			//OLD: unsigned int dataset_counter = 0;
			dataset_counter = 0;

			if(list_of_datasets[dataset_counter] == 1) {
				data_read[dataset_counter] = std::stof(ptr, NULL);
				dataset_counter++;
			}
			else {
				#ifdef WINDOWS_OS
					ptr = strtok_s(NULL, ",;", &next_ptr); //windows version
				#elif !WINDOWS_OS
					ptr = strtok_r(NULL, ",;", &next_ptr);
				#endif
			}

			for(;dataset_counter<num_of_datasets;dataset_counter++) {
				for(unsigned int c_ix=list_of_datasets[dataset_counter-1]; c_ix<list_of_datasets[dataset_counter]; c_ix++)
				{
					#ifdef WINDOWS_OS
						ptr = strtok_s(NULL, ",;", &next_ptr); //windows version
					#elif !WINDOWS_OS
						ptr = strtok_r(NULL, ",;", &next_ptr);
					#endif 

				}
				data_read[dataset_counter] = std::stof(ptr, NULL);
			}
			return true;
		}
	}
	return false;
}

float CSVreaderModule :: get_value_of_field(unsigned int field) {
	//TODO: Bessere Fehlerbehandlung.. also nciht einfach 0 returnen, wenn kein richtiges FEld!!!
	if(field < num_of_datasets) {
		return data_read[field];
	}

	return 0.0;
}



//TODO: �berarbeiten nach folgendem Beispiel https://msdn.microsoft.com/en-us/library/ftsafwz3.aspx
bool CSVreaderModule :: read_field() {
	if(fpointer)
	{ 
        char readrow[STRINGLENGTH] = "", electedfield[STRINGLENGTH] = ""; 

		//TODO: move following for-loop to "initialize_csvreader(...)
		for(;row<start_row; row++) {

			if(!fgets(readrow, STRINGLENGTH, fpointer))
				return false;
		}

		if(fgets (readrow, STRINGLENGTH, fpointer))
		{
			char *ptr, *next_ptr;
			//TODO: make delimiter configurable!
			#ifdef WINDOWS_OS
				ptr = strtok_s(readrow, ",;", &next_ptr);	//windows version
			#elif !WINDOWS_OS
				ptr = strtok_r(readrow, ",;", &next_ptr);
			#endif 	
			
			for(unsigned int d_ix=1; d_ix<column; d_ix++) {
				#ifdef WINDOWS_OS
					ptr = strtok_s(NULL, ",;", &next_ptr);	//windows version
				#elif !WINDOWS_OS
					ptr = strtok_r(NULL, ",;", &next_ptr);
				#endif 	
			}
			
			input_data = std::stof(ptr, NULL);
			return true;
		}
	}
	return false;
}


bool CSVreaderModule :: get_next_value(float* value) {

	if(flag_csv_reader_configured) {
		if(read_field()) {
			*value = input_data;
			return true;
		}
	}

	return false;
}

void CSVreaderModule :: reset_row(const int row)
{
	this->row = row;
}

void CSVreaderModule:: set_position_fpointer_to_start()
{
	long int cur_pos;
	if(this->fpointer) {
		cur_pos = ftell(this->fpointer);
		rewind(this->fpointer);
	}
}


//TODO: flag_csv_reader_configured abfragen
void CSVreaderModule :: close_file() {
	fclose(fpointer); 
}

CSVreaderModule :: ~CSVreaderModule(){
	if(fpointer) {
		close_file();
	}
}
