/*
  This file is part of CDO. CDO is a collection of Operators to manipulate and analyse Climate model Data.

  Author: Uwe Schulzweida
          Oliver Heidmann

*/

#include <cassert>
#include <cstring>
#include <cctype>
#include <iomanip>
#include <sstream>
#include <algorithm>
#include <cdi.h>

#include <regex>

std::vector<std::string>
split_string(const std::string &str, const std::string &delimiter)
{
  std::regex regex(delimiter);
  return { std::sregex_token_iterator(str.begin(), str.end(), regex, -1), std::sregex_token_iterator() };
}

std::string
string_to_upper(std::string p_str)
{
  std::transform(p_str.begin(), p_str.end(), p_str.begin(), [](unsigned char c) { return std::toupper(c); });
  return p_str;
}

std::string
string_to_lower(std::string p_str)
{
  std::transform(p_str.begin(), p_str.end(), p_str.begin(), [](unsigned char c) { return std::tolower(c); });
  return p_str;
}

void
cstr_to_lower_case(char *str)
{
  if (str)
    for (size_t i = 0; str[i]; ++i) str[i] = (char) tolower((int) str[i]);
}

void
cstr_to_upper_case(char *str)
{
  if (str)
    for (size_t i = 0; str[i]; ++i) str[i] = (char) toupper((int) str[i]);
}

static void
trim_flt(char *ss)
{
  char *cp = ss;
  if (*cp == '-') cp++;
  while (isdigit((int) *cp) || *cp == '.') cp++;
  if (*--cp == '.') return;

  char *ep = cp + 1;
  while (*cp == '0') cp--;
  cp++;
  if (cp == ep) return;
  while (*ep) *cp++ = *ep++;
  *cp = '\0';

  return;
}

std::string
get_scientific(double p_float_string)
{
  std::stringstream s;
  s << std::defaultfloat << p_float_string;
  return s.str();
}

char *
double_to_att_str(int digits, char *attstr, size_t len, double value)
{
  const auto ret = snprintf(attstr, len, "%#.*g", digits, value);
  assert(ret != -1 && ret < (int) len);
  trim_flt(attstr);
  return attstr;
}

const char *
tunit_to_cstr(int tunits)
{
  // clang-format off
  if      (tunits == TUNIT_YEAR)       return "years";
  else if (tunits == TUNIT_MONTH)      return "months";
  else if (tunits == TUNIT_DAY)        return "days";
  else if (tunits == TUNIT_12HOURS)    return "12hours";
  else if (tunits == TUNIT_6HOURS)     return "6hours";
  else if (tunits == TUNIT_3HOURS)     return "3hours";
  else if (tunits == TUNIT_HOUR)       return "hours";
  else if (tunits == TUNIT_30MINUTES)  return "30minutes";
  else if (tunits == TUNIT_QUARTER)    return "15minutes";
  else if (tunits == TUNIT_MINUTE)     return "minutes";
  else if (tunits == TUNIT_SECOND)     return "seconds";
  else                                 return "unknown";
  // clang-format on
}

const char *
calendar_to_cstr(int calendar)
{
  // clang-format off
  if      (calendar == CALENDAR_STANDARD)  return "standard";
  else if (calendar == CALENDAR_GREGORIAN) return "gregorian";
  else if (calendar == CALENDAR_PROLEPTIC) return "proleptic_gregorian";
  else if (calendar == CALENDAR_360DAYS)   return "360_day";
  else if (calendar == CALENDAR_365DAYS)   return "365_day";
  else if (calendar == CALENDAR_366DAYS)   return "366_day";
  else                                     return "unknown";
  // clang-format on
}
