/*
  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.
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <string>
#include <cassert>

#include "cdoStream.h"
#include "cdo_options.h"

static int nextCdoStreamID = 1;

CdoStream::~CdoStream() {}
CdoStream::CdoStream() : m_cdoStreamID(nextCdoStreamID++)
{
  isopen = false;
  ispipe = false;
  m_vlistID = -1;
  m_tsID = -1;
  m_filetype = CDI_UNDEFID;
  m_name = "";
  m_varID = -1;
  m_nvals = 0;
  m_fileID = 0;
}

int
CdoStream::get_id()
{
  return m_cdoStreamID;
}

int
CdoStream::getTsID()
{
  return m_tsID;
}

int
CdoStream::getVarID()
{
  return m_varID;
}

int
CdoStream::getVlistID()
{
  return m_vlistID;
}

void
CdoStream::defDatarangeList(int p_vlistID)
{
  const auto filetype = m_filetype;

  if (m_vlistID != -1) cdo_abort("Internal problem, vlist already defined!");

  if (m_datarangelist.size() != 0) cdo_abort("Internal problem, datarangelist already allocated!");

  const auto nvars = vlistNvars(p_vlistID);
  assert(nvars > 0);

  m_datarangelist.resize(nvars);

  for (int varID = 0; varID < nvars; ++varID)
    {
      m_datarangelist[varID].gridsize = gridInqSize(vlistInqVarGrid(p_vlistID, varID));
      m_datarangelist[varID].datatype = vlistInqVarDatatype(p_vlistID, varID);
      m_datarangelist[varID].missval = vlistInqVarMissval(p_vlistID, varID);
      m_datarangelist[varID].addoffset = vlistInqVarAddoffset(p_vlistID, varID);
      m_datarangelist[varID].scalefactor = vlistInqVarScalefactor(p_vlistID, varID);

      m_datarangelist[varID].check_datarange = false;

      const bool laddoffset = IS_NOT_EQUAL(m_datarangelist[varID].addoffset, 0);
      const bool lscalefactor = IS_NOT_EQUAL(m_datarangelist[varID].scalefactor, 1);

      auto datatype = m_datarangelist[varID].datatype;

      if (filetype == CDI_FILETYPE_NC || filetype == CDI_FILETYPE_NC2 || filetype == CDI_FILETYPE_NC4
          || filetype == CDI_FILETYPE_NC4C || filetype == CDI_FILETYPE_NC5)
        {
          if (datatype == CDI_DATATYPE_UINT8
              && (filetype == CDI_FILETYPE_NC || filetype == CDI_FILETYPE_NC2 || filetype == CDI_FILETYPE_NC5))
            {
              datatype = CDI_DATATYPE_INT16;
              m_datarangelist[varID].datatype = datatype;
            }

          if (datatype == CDI_DATATYPE_UINT16
              && (filetype == CDI_FILETYPE_NC || filetype == CDI_FILETYPE_NC2 || filetype == CDI_FILETYPE_NC5))
            {
              datatype = CDI_DATATYPE_INT32;
              m_datarangelist[varID].datatype = datatype;
            }

          if (laddoffset || lscalefactor)
            {
              if (datatype == CDI_DATATYPE_INT8 || datatype == CDI_DATATYPE_UINT8 || datatype == CDI_DATATYPE_INT16
                  || datatype == CDI_DATATYPE_UINT16)
                m_datarangelist[varID].check_datarange = true;
            }
          else if (Options::CheckDatarange)
            {
              m_datarangelist[varID].check_datarange = true;
            }
        }
    }

  m_vlistID = p_vlistID;  // used for -r/-a
}
