text: /*
   * (C) Copyright 1996-2016 ECMWF.
   *
   * This software is licensed under the terms of the Apache Licence Version 2.0
   * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
   * In applying this licence, ECMWF does not waive the privileges and immunities
   * granted to it by virtue of its status as an intergovernmental organisation nor
   * does it submit to any jurisdiction.
   */
  
  
  #ifndef EpsJSon_H
  #define EpsJSon_H
  
  #include "magics.h"
  
  
  #include "WrepJSonAttributes.h"
  
  #include "Data.h"
  #include "MagDateTime.h"
  #include "MagicsDecoder.h"
  #include "UserPoint.h"
  #include "json_spirit.h"
  
  #include <limits>
  #include "Matrix.h"
  
  namespace magics {
  
  
  struct InputWrep {
      bool empty() { return steps_.empty(); }
      map<string, vector<double>> values_;
      map<string, double> info_;
      map<string, vector<vector<double>>> ensembleValues_;
  
      vector<double> steps_;
      vector<double> levels_;
      int index(double val) {
          if (val == -1) {
              return 0;
          }
          if (steps_.empty())
              return -1;
          vector<double>::iterator step = steps_.begin();
          int index                     = 0;
          while (*step != val) {
              ++step;
              if (step == steps_.end()) {
                  return -1;
              }
              index++;
          }
          return index;
      }
      void print() {
          cout << "InputWrep" << endl;
          string sep = "steps[";
          for (vector<double>::iterator step = steps_.begin(); step != steps_.end(); ++step) {
              cout << sep << *step;
              sep = ", ";
          }
          cout << "]" << endl;
          for (map<string, double>::iterator value = info_.begin(); value != info_.end(); ++value) {
              cout << value->first << " = " << value->second << endl;
          }
          for (map<string, vector<double>>::iterator value = values_.begin(); value != values_.end(); ++value) {
              string sep = value->first + "[";
              for (vector<double>::iterator val = value->second.begin(); val != value->second.end(); ++val) {
                  std::cout << sep << *val;
                  sep = ", ";
              }
              cout << "]" << endl;
          }
          for (map<string, vector<vector<double>>>::iterator value = ensembleValues_.begin();
               value != ensembleValues_.end(); ++value) {
              string sep = value->first + "[";
              for (vector<vector<double>>::iterator val = value->second.begin(); val != value->second.end(); ++val) {
                  std::cout << sep << val->size();
                  sep = ", ";
              }
              cout << "]" << endl;
          }
      }
  };
  
  
  class WrepJSon : public Data, public PointsList, public WrepJSonAttributes {
  public:
      WrepJSon();
      virtual ~WrepJSon();
  
      typedef void (WrepJSon::*Method)(const json_spirit::Value&);
      typedef void (WrepJSon::*Decoder)();
      typedef void (WrepJSon::*TransformationHandler)(Transformation&);
      typedef double (WrepJSon::*HeightCorrection)(double);
      typedef json_spirit::Value (WrepJSon::*MetaMethod)();
      map<string, Method> methods_;
      map<string, Decoder> decoders_;
      map<string, TransformationHandler> transformationHandlers_;
      map<string, HeightCorrection> heightCorrections_;
      map<string, MetaMethod> metaMethods_;
  
      void efi();
      void cdf();
      void eps();
      void basic();
      void data();
      void profile();
      void tephigram();
      void hodograph();
      void cape();
  
  
      void profile(Transformation&);
      void eps(Transformation&);
      void efi(Transformation&);
      void cdf(Transformation&);
  
      // Simple  input
      void x_values(const json_spirit::Value&);
      void y_values(const json_spirit::Value&);
      void values(const json_spirit::Value&);
      void x_date_values(const json_spirit::Value&);
      void y_date_values(const json_spirit::Value&);
  
      // tephigram
      void param(const json_spirit::Value&);
      void levels(const json_spirit::Value&);
      void data(const json_spirit::Value&, vector<double>&);
  
      // Hodograph
      void hodo_u(const json_spirit::Value&);
      void hodo_v(const json_spirit::Value&);
  
      // Cape
      void cape0(const json_spirit::Value&);
      void cape1(const json_spirit::Value&);
      void cape2(const json_spirit::Value&);
      void cape3(const json_spirit::Value&);
      void cape_dig(const json_spirit::Value&);
  
  
      // common
      void location(const json_spirit::Value&);
      void station_name(const json_spirit::Value&);
      void valid_time(const json_spirit::Value&);
      void epsz(const json_spirit::Value&);
      void detz(const json_spirit::Value&);
      void date(const json_spirit::Value&);
      void expver(const json_spirit::Value&);
      void height(const json_spirit::Value&);
      void time(const json_spirit::Value&);
      void step(const json_spirit::Value&);
      void api(const json_spirit::Value&);
  
      virtual void parameter(const json_spirit::Value&);
      virtual void eps(const json_spirit::Value&);
      virtual void clim(const json_spirit::Value&);
      virtual void efi(const json_spirit::Value&);
      void dig(const json_spirit::Value&);
      void ignore(const json_spirit::Value&) {}
      void missing(const json_spirit::Value&);
      void mask(const json_spirit::Value&);
      void station(const json_spirit::Value&);
      void metadata(const json_spirit::Value&);
      void temperature_correction(const json_spirit::Value&);
      void points_along_meridian(const json_spirit::Value&);
  
  
      json_spirit::Value temperature_correction();
      json_spirit::Value temperature_adjustment();
      json_spirit::Value eps_resolution();
      json_spirit::Value deterministic_resolution();
      json_spirit::Value height();
      json_spirit::Value station_name();
  
      MatrixHandler& matrix();
      void customisedPoints(const std::set<string>&, CustomisedPointsList&);
      void customisedPoints(const Transformation&, const std::set<string>&, CustomisedPointsList&);
  
      virtual void set(const map<string, string>& map) { WrepJSonAttributes::set(map); }
      virtual void set(const XmlNode& node) { WrepJSonAttributes::set(node); }
  
      virtual void visit(Transformation&);
      virtual void visit(TextVisitor&);
      void visit(const XmlNode& node);
  
      virtual void decode();
  
      double correctDetz(double);
      double correctEpsz(double);
  
      void visit(MetaDataVisitor&);
      void points(const Transformation&, vector<UserPoint>&);
      void customisedPoints(const Transformation& t, const std::set<string>& n, CustomisedPointsList& out, bool all) {
          customisedPoints(t, n, out);
      }
      PointsHandler& points(const Transformation& t, bool);
  
  
  protected:
      //! Method to print string about this class on to a stream of type ostream (virtual).
      virtual void print(ostream&) const;
      DateTime base_;
      vector<CustomisedPoint*> points_;
      PointsList list_;
      double minx_;
      double maxx_;
      double minClim_;
      double maxClim_;
      double miny_;
      double maxy_;
      double shift_;
      double missing_;
      double latitude_;
      double longitude_;
      double height_;
      double epsz_;
      double detz_;
      double scaling_factor_;
      double offset_factor_;
      double mask_;
      string station_name_;
      double station_latitude_;
      double station_longitude_;
      string date_;
      string time_;
      int step_;
      string file_;
      string valid_time_;
      string expver_;
      string api_;
      string capekey_;
      string tephikey_;
  
      json_spirit::Value metadata_;
      InputWrep values_;
      InputWrep* current_;
  
      InputWrep clim_;
  
      map<string, InputWrep> eps_;
      map<string, InputWrep> efi_;
      map<string, InputWrep> capes_;
  
  
      int points_along_meridian_;
      Matrix matrix_;
  
      bool xdate_;
      DateTime xBase_;
      bool ydate_;
      DateTime yBase_;
      bool regular_;
  
  private:
      //! Copy constructor - No copy allowed
      WrepJSon(const WrepJSon&);
      //! Overloaded << operator to copy - No copy allowed
      WrepJSon& operator=(const WrepJSon&);
  
      // -- Friends
      //! Overloaded << operator to call print().
      friend ostream& operator<<(ostream& s, const WrepJSon& p) {
          p.print(s);
          return s;
      }
  };
  
  }  // namespace magics
  #endif
  