#include <cdi.h>
#include <cstring>
#include <cstdlib>

#include "cdi_int.h"
#include "cdo_default_values.h"
#include "cdo_cdi_wrapper.h"

const char *
cdi_filetype_to_str(int filetype)
{
  switch (filetype)
    {
    // clang-format off
    case CDI_FILETYPE_GRB:  return "GRIB";
    case CDI_FILETYPE_GRB2: return "GRIB2";
    case CDI_FILETYPE_NC:   return "NetCDF";
    case CDI_FILETYPE_NC2:  return "NetCDF2";
    case CDI_FILETYPE_NC4:  return "NetCDF4";
    case CDI_FILETYPE_NC4C: return "NetCDF4 classic";
    case CDI_FILETYPE_NC5:  return "NetCDF5";
    case CDI_FILETYPE_SRV:  return "SERVICE";
    case CDI_FILETYPE_EXT:  return "EXTRA";
    case CDI_FILETYPE_IEG:  return "IEG";
    default:                return "";
      // clang-format on
    }
}

const char *
cdi_datatype_to_str(int datatype)
{
  static char str[20];
  str[0] = 0;
  if (datatype > 0 && datatype <= 32) snprintf(str, sizeof(str), "P%d", datatype);

  // clang-format off
  if      (datatype == CDI_DATATYPE_PACK  ) return "P0";
  else if (datatype > 0 && datatype <= 32 ) return str;
  else if (datatype == CDI_DATATYPE_CPX32 ) return "C32";
  else if (datatype == CDI_DATATYPE_CPX64 ) return "C64";
  else if (datatype == CDI_DATATYPE_FLT32 ) return "F32";
  else if (datatype == CDI_DATATYPE_FLT64 ) return "F64";
  else if (datatype == CDI_DATATYPE_INT8  ) return "I8";
  else if (datatype == CDI_DATATYPE_INT16 ) return "I16";
  else if (datatype == CDI_DATATYPE_INT32 ) return "I32";
  else if (datatype == CDI_DATATYPE_UINT8 ) return "U8";
  else if (datatype == CDI_DATATYPE_UINT16) return "U16";
  else if (datatype == CDI_DATATYPE_UINT32) return "U32";
  else                                      return "";
  // clang-format on
}

int
cdo_str_to_datatype(const char *datatypestr)
{
  auto len = strlen(datatypestr);
  if (len > 1)
    {
      const auto ilen = atoi(datatypestr + 1);
      // clang-format off
      if      (strncmp(datatypestr, "P0", len) == 0)     return CDI_DATATYPE_PACK;
      else if (strncmp(datatypestr, "P", 1) == 0 && ilen > 0 && ilen <= 32) return atoi(datatypestr + 1);
      else if (strncmp(datatypestr, "C32", len) == 0)    return CDI_DATATYPE_CPX32;
      else if (strncmp(datatypestr, "C64", len) == 0)    return CDI_DATATYPE_CPX64;
      else if (strncmp(datatypestr, "F32", len) == 0)    return CDI_DATATYPE_FLT32;
      else if (strncmp(datatypestr, "F64", len) == 0)    return CDI_DATATYPE_FLT64;
      else if (strncmp(datatypestr, "I8", len) == 0)     return CDI_DATATYPE_INT8;
      else if (strncmp(datatypestr, "I16", len) == 0)    return CDI_DATATYPE_INT16;
      else if (strncmp(datatypestr, "I32", len) == 0)    return CDI_DATATYPE_INT32;
      else if (strncmp(datatypestr, "U8", len) == 0)     return CDI_DATATYPE_UINT8;
      else if (strncmp(datatypestr, "U16", len) == 0)    return CDI_DATATYPE_UINT16;
      else if (strncmp(datatypestr, "U32", len) == 0)    return CDI_DATATYPE_UINT32;
      else if (strncmp(datatypestr, "real", len) == 0)   return CDI_DATATYPE_FLT32;
      else if (strncmp(datatypestr, "double", len) == 0) return CDI_DATATYPE_FLT64;
      // clang-format on
    }

  return -1;
}

int
cdo_taxis_create(int taxisType)
{
  if (CdoDefault::TaxisType != CDI_UNDEFID) taxisType = CdoDefault::TaxisType;
  return taxisCreate(taxisType);
}

void cdo_taxis_copy_timestep(int taxisIDdes, int taxisIDsrc)
{
  taxisCopyTimestep(taxisIDdes, taxisIDsrc);
}

void
cdo_def_table_id(int tableID)
{
  cdiDefTableID(tableID);
}

void
grid_gen_xvals(int xsize, double xfirst, double xlast, double xinc, double *xvals)
{
  gridGenXvals(xsize, xfirst, xlast, xinc, xvals);
}

void
grid_gen_yvals(int gridtype, int ysize, double yfirst, double ylast, double yinc, double *yvals)
{
  gridGenYvals(gridtype, ysize, yfirst, ylast, yinc, yvals);
}
