#include "CSVreaderModule.h"
#include <cstring>
#include <iostream>

#define STRINGLENGTH 5000

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;
}

CSVreaderModule::CSVreaderModule() {
  set_name(NO_NAME);
  flag_csv_reader_configured = false;
}

CSVreaderModule::CSVreaderModule(const 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(const 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;
      // TODO: make delimiter configurable!
      ptr = strtok(readrow, ",;");
      // 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 {
        ptr = strtok(NULL, ",;");
      }

      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++) {
          ptr = strtok(NULL, ",;");
        }
        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;
      // TODO: make delimiter configurable!
      ptr = strtok(readrow, ",;");

      for (unsigned int d_ix = 1; d_ix < column; d_ix++) {
        ptr = strtok(NULL, ",;");
      }

      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;
}

// TODO: flag_csv_reader_configured abfragen
void CSVreaderModule::close_file() { fclose(fpointer); }
