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

  Copyright (C) 2003-2021 Uwe Schulzweida, <uwe.schulzweida AT mpimet.mpg.de>
  See COPYING file for copying and redistribution conditions.

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; version 2 of the License.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
*/

#include <vector>
#include <string>
#include <string.h>
#include <time.h>

#include <cdi.h>

#include "cdo_options.h"
#include "cdi_uuid.h"

static int numVlist;
static constexpr int maxVlist = 256;
static int vlistHistory[maxVlist];

static char strtime[32];
static char datetimestr[32];

static void
init_strtime()
{
  auto tp = time(nullptr);
  if (tp != -1)
    {
      auto ltime = localtime(&tp);
      (void) strftime(strtime, sizeof(strtime), "%a %b %d %H:%M:%S %Y: ", ltime);
      (void) strftime(datetimestr, sizeof(datetimestr), "%Y-%m-%dT%H:%M:%SZ", ltime);
    }
}

static const char *
get_strtimeptr()
{
  if (strlen(strtime) == 0) init_strtime();

  return strtime;
}

void
cdo_append_history(int vlistID, const char *histstring)
{
  for (int i = 0; i < numVlist; ++i)
    if (vlistHistory[i] == vlistID) return;

  if (numVlist < maxVlist) vlistHistory[numVlist++] = vlistID;

  static const char *historyAttrName = "history";

  if (Options::CDO_Reset_History) cdiDelAtt(vlistID, CDI_GLOBAL, historyAttrName);

  if (!Options::CDO_Append_History) return;

  std::vector<char> ghistory;
  const auto atttype = cdiInqAttType(vlistID, CDI_GLOBAL, historyAttrName);
  if (atttype == CDI_DATATYPE_TXT)
    {
      int ghistorysize = cdiInqAttLen(vlistID, CDI_GLOBAL, historyAttrName);
      if (ghistorysize < 0) ghistorysize = 0;
      if (ghistorysize > 0)
        {
          ghistorysize++;
          ghistory.resize(ghistorysize);
          cdiInqAttTxt(vlistID, CDI_GLOBAL, historyAttrName, ghistorysize, ghistory.data());
          ghistory[ghistorysize - 1] = 0;
          ghistorysize = strlen(ghistory.data());
        }
    }
  else if (atttype != -1)
    {
      return;
    }

  std::string history;
  auto strtimeptr = get_strtimeptr();
  if (strtimeptr) history = strtimeptr;
  history += histstring;

  if (!ghistory.empty())
    {
      history += "\n";
      history += ghistory.data();
    }

  cdiDefAttTxt(vlistID, CDI_GLOBAL, historyAttrName, strlen(history.c_str()), history.c_str());
}

void
cdo_def_creation_date(int vlistID)
{
  if (strlen(datetimestr) == 0) init_strtime();
  cdiDefAttTxt(vlistID, CDI_GLOBAL, "creation_date", (int) strlen(datetimestr), datetimestr);
}

static void
get_uuid(char *uuidstr)
{
  unsigned char uuid[CDI_UUID_SIZE];
  cdiCreateUUID(uuid);
  cdiUUID2Str(uuid, uuidstr);
}

void
cdo_def_tracking_id(int vlistID, const char *uuid_attribute)
{
  char uuidstr[uuidNumHexChars + 1] = { 0 };
  get_uuid(uuidstr);
  cdiDefAttTxt(vlistID, CDI_GLOBAL, uuid_attribute, uuidNumHexChars, uuidstr);
}
