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

  Copyright (C) 2003-2020 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 <cdi.h>

#include "field.h"
#include "cdo_vlist.h"
#include "cdo_options.h"

void
fieldsFromVlistKernel(const int vlistID, FieldVector2D &field2D, int ptype, bool lfill, double fillValue)
{
  const auto nvars = vlistNvars(vlistID);
  field2D.resize(nvars);

  for (int varID = 0; varID < nvars; ++varID)
    {
      const auto gridID = vlistInqVarGrid(vlistID, varID);
      const auto gridsize = gridInqSize(gridID);
      const size_t nwpv = vlistInqNWPV(vlistID, varID);  // number of words per value; real:1  complex:2
      const auto size = gridsize * nwpv;
      const auto zaxisID = vlistInqVarZaxis(vlistID, varID);
      const auto nlevels = zaxisInqSize(zaxisID);
      const auto missval = vlistInqVarMissval(vlistID, varID);

      field2D[varID].resize(nlevels);

      for (int levelID = 0; levelID < nlevels; ++levelID)
        {
          auto &field = field2D[varID][levelID];
          field.nwpv = nwpv;
          field.grid = gridID;
          field.size = size;
          field.memType = (ptype & FIELD_FLT) ? MemType::Float : MemType::Native;
          field.missval = missval;

          if (ptype & FIELD_VEC)
            {
              if (ptype & FIELD_FLT)
                {
                  if (lfill)
                    field.resizef(size, (float) fillValue);
                  else
                    field.resizef(size);
                }
              else
                {
                  if (lfill)
                    field.resize(size, fillValue);
                  else
                    field.resize(size);
                }
            }
        }
    }
}

void
fieldsFromVlist(const int vlistID, FieldVector2D &field2D)
{
  fieldsFromVlistKernel(vlistID, field2D, 0, false, 0);
}

void
fieldsFromVlist(const int vlistID, FieldVector2D &field2D, int ptype)
{
  fieldsFromVlistKernel(vlistID, field2D, ptype, false, 0);
}

void
fieldsFromVlist(const int vlistID, FieldVector2D &field2D, int ptype, double fillValue)
{
  fieldsFromVlistKernel(vlistID, field2D, ptype, true, fillValue);
}
