#include "openxlsx.h"


// [[Rcpp::export]]
IntegerVector map_cell_types_to_integer(CharacterVector t){

  // 0: "n"
  // 1: "s"
  // 2: "b"
  // 3: "str"
  // 4: "e"
  // 9: "h"

  size_t n = t.size();
  IntegerVector t_res(n);

  for (size_t i = 0; i < n; i++) {

    if (CharacterVector::is_na(t[i])) {
      t_res[i] = NA_INTEGER;
    } else if (t[i] == "n") {
      t_res[i] = 0;
    } else if (t[i] == "s") {
      t_res[i] = 1;
    } else if (t[i] == "b") {
      t_res[i] = 2;
    } else if (t[i] == "str") {
      t_res[i] = 3;
    } else if (t[i] == "e") {
      t_res[i] = 4;
    } else if (t[i] == "inlineStr") {
      t_res[i] = 5;
    }

  }

  return t_res;

}


// [[Rcpp::export]]
CharacterVector map_cell_types_to_char(IntegerVector t){

  // 0: "n"
  // 1: "s"
  // 2: "b"
  // 3: "str"
  // 4: "e"
  // 9: "h"

  size_t n = t.size();
  CharacterVector t_res(n);

  for (size_t i = 0; i < n; i++) {

    if (IntegerVector::is_na(t[i])) {
      t_res[i] = NA_STRING;
    } else if (t[i] == 0){
      t_res[i] = "n";
    } else if (t[i] == 1){
      t_res[i] = "s";
    } else if (t[i] == 2){
      t_res[i] = "b";
    } else if (t[i] == 3){
      t_res[i] = "str";
    } else if (t[i] == 4){
      t_res[i] = "e";
    } else if (t[i] == 5){
      t_res[i] = "inlineStr";
    } else {
      t_res[i] = "s";
    }

  }

  return t_res;

}


// [[Rcpp::export]]
IntegerVector build_cell_types_integer(CharacterVector classes, int n_rows){

  // 0: "n"
  // 1: "s"
  // 2: "b"
  // 9: "h"
  // 4: TBC
  // 5: TBC

  size_t n_cols = classes.size();
  IntegerVector col_t(n_cols);

  for(size_t i = 0; i < n_cols; i++){

    if ((classes[i] == "numeric") || (classes[i] == "integer") || (classes[i] == "raw")) {
      col_t[i] = 0;
    } else if (classes[i] == "character"){
      col_t[i] = 1;
    } else if (classes[i] == "logical"){
      col_t[i] = 2;
    } else if (classes[i] == "hyperlink"){
      col_t[i] = 9;
    } else if (classes[i] == "openxlsx_formula"){
      col_t[i] = NA_INTEGER;
    } else {
      col_t[i] = 1;
    }

  }

  IntegerVector cell_types = rep(col_t, n_rows);

  return cell_types;

}


// [[Rcpp::export]]
CharacterVector buildCellTypes(CharacterVector classes, int nRows){

  int nCols = classes.size();
  CharacterVector colLabels(nCols);
  for(int i=0; i < nCols; i++){

    if ((classes[i] == "numeric") || (classes[i] == "integer") || (classes[i] == "raw")) {
      colLabels[i] = "n";
    } else if (classes[i] == "character") {
      colLabels[i] = "s";
    } else if (classes[i] == "logical") {
      colLabels[i] = "b";
    } else if (classes[i] == "hyperlink") {
      colLabels[i] = "h";
    } else if (classes[i] == "openxlsx_formula") {
      colLabels[i] = NA_STRING;
    } else {
      colLabels[i] = "s";
    }

  }

  CharacterVector cellTypes = rep(colLabels, nRows);

  return wrap(cellTypes);
}


// [[Rcpp::export]]
List build_cell_merges(List comps){

  size_t nMerges = comps.size();
  List res(nMerges);

  for (size_t i =0; i < nMerges; i++) {
    IntegerVector col = convert_from_excel_ref(comps[i]);
    CharacterVector comp = comps[i];
    IntegerVector row(2);

    for (size_t j = 0; j < 2; j++) {
      std::string rt(comp[j]);
      rt.erase(std::remove_if(rt.begin(), rt.end(), ::isalpha), rt.end());
      row[j] = atoi(rt.c_str());
    }

    size_t ca(col[0]);
    size_t ck = size_t(col[1]) - ca + 1;

    std::vector<int> v(ck) ;
    for (size_t j = 0; j < ck; j++)
      v[j] = j + ca;

    size_t ra(row[0]);

    size_t rk = int(row[1]) - ra + 1;
    std::vector<int> r(rk) ;
    for (size_t j = 0; j < rk; j++)
      r[j] = j + ra;

    CharacterVector M(ck*rk);
    int ind = 0;
    for (size_t j = 0; j < ck; j++) {
      for (size_t k = 0; k < rk; k++) {
        char name[30];
        snprintf(&(name[0]), sizeof(name), "%d-%d", r[k], v[j]);
        M(ind) = name;
        ind++;
      }
    }

    res[i] = M;
  }

  return wrap(res) ;

}


// [[Rcpp::export]]
List buildCellList(CharacterVector r, CharacterVector t, CharacterVector v) {

  //Valid combinations
  //  r t v
  //  T	F	F
  //  T	T	T
  //  F F	F
  //  T F	T (must be a formula)

  int n = r.size();
  List cells(n);
  LogicalVector hasV = !is_na(v);
  LogicalVector hasR = !is_na(r);
  LogicalVector hasT = !is_na(t);

  for(int i=0; i < n; i++){

    if (hasR[i]){

      if (hasV[i]){

        if (hasT[i]){

          //  r t v
          //  T	T	T (2)
          cells[i] = CharacterVector::create(
            Named("r") = r[i],
            Named("t") = t[i],
            Named("v") = v[i],
            Named("f") = NA_STRING
          );

        } else {

          //  r t f
          //  T	T	T (4 - formula)


        }

      } else {

        //  r t v
        //  T	F	F	(1)
        cells[i] = CharacterVector::create(
          Named("r") = r[i],
          Named("t") = NA_STRING,
          Named("v") = NA_STRING,
          Named("f") = NA_STRING
        );
      }

    } else {

      //  r t v
      //  F F	F	(3)
      cells[i] = CharacterVector::create(
        Named("r") = NA_STRING,
        Named("t") = NA_STRING,
        Named("v") = NA_STRING,
        Named("f") = NA_STRING
      );
    }

  } // end of for loop

  return wrap(cells) ;
}
