#include "sdsl/suffix_arrays.hpp"
#include <iostream>
#include <stdexcept>

using csa_t =
  sdsl::csa_wt<
    sdsl::wt_huff<
      sdsl::bit_vector,
      sdsl::rank_support_v5<>,
      sdsl::select_support_scan<>,
      sdsl::select_support_scan<0>
    >,
    1<<20,
    1<<20
  >;

extern "C" int csa_build(const char * input_file_cstr, const char * output_file_cstr) {
  try {
    std::string input_file = input_file_cstr;
    std::string output_file = output_file_cstr;
    csa_t csa;
    sdsl::construct(csa, input_file, 1);
    if(!sdsl::store_to_file(csa, output_file)) {
      throw std::runtime_error("store_to_file returned false");
    }
  } catch(const std::exception & e) {
    std::cerr << "csa_build exception: " << e.what() << "\n";
    return 0;
  }
  return 1;
}

extern "C" csa_t * csa_load(const char * input_file_cstr) {
  csa_t * csa = nullptr;
  try {
    csa = new csa_t;
  } catch(const std::exception & e) {
    std::cerr << "csa_load failed to allocate: " << e.what() << "\n";
    return nullptr;
  }
  try {
    std::string input_file = input_file_cstr;
    if(!sdsl::load_from_file(*csa, input_file)) {
      throw std::runtime_error("load_from_file returned false");
    }
  } catch(const std::exception & e) {
    std::cerr << "csa_load exception: " << e.what() << "\n";
    delete csa;
    csa = nullptr;
  }
  return csa;
}

extern "C" void csa_free(csa_t * csa) {
  if(csa == nullptr) {
    std::cerr << "csa_free passed nullptr\n";
    return;
  }
  delete csa;
}

extern "C" ssize_t csa_count(csa_t * csa, const char * str) {
  if(csa == nullptr) {
    std::cerr << "csa_count passed nullptr\n";
    return -1;
  }
  try {
    return sdsl::count(*csa, str);
  } catch(const std::exception & e) {
    std::cerr << "csa_count exception: " << e.what() << "\n";
    return -1;
  }
}
