#include <corsika_data/Interface.h>

#include <string>
#include <fstream>
#include <iostream>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/bzip2.hpp>

#include <iostream>
using namespace std;

namespace corsika_data {

  struct DataFile {
    std::ifstream file_in_;
    boost::iostreams::filtering_istream in_;
    DataFile() {}
    ~DataFile() {}
    void Open(const char *name) {
      if (file_in_.is_open()) {
	std::cout << "DataFile is still open! Close it" << std::endl;
	file_in_.close();
      }
      std::string s(name);
      auto i1 = s.find_first_not_of(" \t\r\n");
      auto i2 = s.find_first_of(" \t\r\n", i1);
      std::string trimmed(s.substr(i1, i2-i1));
      file_in_.open(trimmed, ios_base::in | ios_base::binary);
      in_.reset();
      in_.push(boost::iostreams::bzip2_decompressor());
      in_.push(file_in_);
    }
    void Close() { file_in_.close(); }
    void FillArray(double* data, const int& length) {
      for(int i=0; i<length; i++)
	in_ >> data[i];
    }
    double ReadNextNumber() {
      double data;
      in_ >> data;
      return data;
    }
    int ReadNextText(std::string& data) {
      std::getline(in_, data, ' ');
      return 0;
    }
  };
  
  DataFile global_DataFile;
  
  void CorDataOpenFile(char* name) { global_DataFile.Open(name); }
  void CorDataFillArray(double* data, const int& length) { global_DataFile.FillArray(data, length); }
  void CorDataCloseFile() { global_DataFile.Close(); }
  double CorDataNextNumber() { return global_DataFile.ReadNextNumber(); }
  int CorDataNextText(char* data, const int length) {
    std::string STR;    
    global_DataFile.ReadNextText(STR);
    for (int i=0; i<length && i<(int)STR.size(); ++i)
      data[i] = STR[i];
    return 0;
  }
  
  
  extern "C" { 
    void cordataopenfile_(char* name) {
      CorDataOpenFile(name);
    }    
    void cordatafillarray_(double* data, const int& length) {
      global_DataFile.FillArray(data, length);
    }
    double cordatanextnumber_() {
      return global_DataFile.ReadNextNumber();
    }
    int cordatanexttext_(char* data, const int length) { return CorDataNextText(data, length); }
    void cordataclosefile_() {
      global_DataFile.Close();
    }
  }
}