/*
  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.
*/
#ifndef SELLIST_H
#define SELLIST_H

#include "pmlist.h"

enum class SelType
{
  UNDEF,
  INT,
  FLT,
  WORD
};

struct SelectEntry
{
  int nvalues;
  std::string key;
  std::vector<std::string> values;
  std::vector<bool> flag;
  std::string txt;
  SelType type;
  std::vector<int> ivalues;
  std::vector<double> dvalues;
  std::vector<const char *> cvalues;
};

class SelectInfo
{
 private:

  void init(const KVList &kvlist);

 public:
  std::vector<SelectEntry> selList;

  SelectInfo(KVList &kvlist) { init(kvlist); }

  void verify() const;
  void print() const;
  int nvalues(const int listIdx) const;
  bool isValidListIdx(const int listIdx) const noexcept
  {
    return (listIdx >= 0 && listIdx < (int) selList.size());
  }
};

#define SELINFO_ADD_INT(name, txt) \
  int name = 0;                    \
  int listIdx_##name = selinfo_add(selInfo, txt, #name, SelType::INT)
#define SELINFO_ADD_FLT(name, txt) \
  double name = 0;                 \
  int listIdx_##name = selinfo_add(selInfo, txt, #name, SelType::FLT)
#define SELINFO_ADD_WORD(name, txt) \
  const char *name = 0;             \
  int listIdx_##name = selinfo_add(selInfo, txt, #name, SelType::WORD)
#define SELINFO_NVAL(name) selInfo.nvalues(listIdx_##name)
#define SELINFO_CHECK_FLAG(name) selinfo_check_flag(selInfo, listIdx_##name)
#define SELINFO_CHECK(name) selinfo_check(selInfo, listIdx_##name, &name)
#define SELINFO_CHECK_DATE(name) selinfo_check_date(selInfo, listIdx_##name, name)
#define SELINFO_CHECK_SEASON(name, month) selinfo_check_season(selInfo, listIdx_##name, month)
#define SELINFO_DEF_FLAG(name, valIdx, flag) selinfo_def_flag(selInfo, listIdx_##name, valIdx, flag)
#define SELINFO_GET_VAL(name, valIdx, val) selinfo_get_val(selInfo, listIdx_##name, valIdx, val)
#define SELINFO_DEF_VAL(name, valIdx, val) selinfo_def_val(selInfo, listIdx_##name, valIdx, val)

int selinfo_add(SelectInfo &selInfo, const char *txt, const char *name, SelType type);
void selinfo_check_flag(const SelectInfo &selInfo, const int listIdx);
bool selinfo_check(SelectInfo &selInfo, int listIdx, void *par);
bool selinfo_check_date(SelectInfo &selInfo, int listIdx, const char *par);
bool selinfo_check_season(SelectInfo &selInfo, int listIdx, int month);
void selinfo_def_flag(SelectInfo &selInfo, int listIdx, int valIdx, bool flag);
void selinfo_get_val(const SelectInfo &selInfo, int listIdx, int valIdx, void *val);
void selinfo_def_val(SelectInfo &selInfo, int listIdx, int valIdx, void *val);

#endif
