/***************************** LICENSE START ***********************************

 Copyright 2012 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#ifndef XSECT_H
#define XSECT_H

/********************************************************************************
  Application for Xsection, Average and Vertical Profile.
  It takes a GRIB file as input (in addition to the values given by the user),
  and produces an NetCDF file as output. There is no metadata on output request,
  only the path to NetCDF file.

  First the GRIB while is read, and info about all parameters and level are stored.
  Then several flags is set, based on the data and the input request, to determine
  how the application should run.

  The file is rewound, and sorted by param, date, time, step and expver. All fields
  with the same values for the sorting parameters are one plot. If any of these
  values change, all data are written out as netcdf variables with names put
  together from the sorting values.
********************************************************************************/

#include "MvXsectFrame.h"

class Xsect : public MvService {

public:

   // Entry point routine
   void serve(MvRequest&,MvRequest&);

   // Process grib data and build all data structures
   bool processData(MvRequest&, ApplicationInfo&, MvRequest& );

   bool getInputParameters( MvRequest&, MvRequest&, ApplicationInfo& );

   void generateKey(string&,int,int,int,int,const char *);

   // Get the application (original) view request
   MvRequest getAppView ( MvRequest& );

   // Consistency check
   bool consistencyCheck( ParamMap&, ApplicationInfo& );

   // Initialise/create netCDF file
   bool initialiseNetcdf( MvNetCDF&, ParamMap&, ApplicationInfo&, int&, MvField&, double* );

   // Write level info to the Netcdf structure
   virtual bool writeLevelInfoNetcdf ( MvNetCDF&, ApplicationInfo&, ParamMap&, MvField* = 0, double* = 0)
      { return true; }

   // Write time info to the Netcdf file
   bool writeTimeInfoNetcdf( MvNetCDF&, ParamMap&, int& );

   // Write geographical coordinates info to the Netcdf file
   virtual bool writeGeoCoordsNetcdf ( MvNetCDF&, ApplicationInfo& );

   // Write global attributes info to the Netcdf file
   virtual bool writeGlobalAttributesNetcdf ( MvNetCDF&, ParamMap&, ApplicationInfo& );

   // Write extra variables to the Netcdf file
   virtual bool generateExtraData( MvNetCDF&, ApplicationInfo&, ParamMap&, MvFieldSetIterator& ) { return true; }

  // Check if action is visualisation related
   bool isVisualise( ApplicationInfo& );

   // Write the data to the netcdf file
   virtual bool generateData( ApplicationInfo&, ParamMap&, MvNetCDF&, MvField&, const string& ) = 0;

   // Get title related to a variable
   virtual string titleVariable( ApplicationInfo&, ParamInfo*) = 0;

   // Compute data values
   virtual bool fillValues( ApplicationInfo&, MvField&, double* ) = 0;

   // Create output request using information from the application
   virtual MvRequest createOutputRequest( ApplicationInfo&, ParamInfo* ) = 0;

   // Create output request using information from the request
   virtual MvRequest createOutputRequest( MvRequest& );

   // Compute number and geographical points
   virtual int computeGeographicalPoints( ApplicationInfo&, MvField* = 0 ) = 0;

protected:

   // Constructor
   Xsect(const char* kw);

   // Destructor
   ~Xsect() {};
   
   void getInitialFieldInfo( MvField&, ApplicationInfo&, double&, double&, double&, double& );
   bool updateTopBottomLevels( ApplicationInfo&, ParamMap&, int, MvFieldSetIterator&, double&, double&, int& );
   bool checkCoordinates( double&, double&, double&, double&);

   // Check if parameters between two requests are consistent
   virtual bool consistencyCheck( MvRequest&, MvRequest& ) = 0;

   bool contourValues( ApplicationInfo&, ParamMap&, MvNetCDF&, MvField&, string );

   // Get application specific parameters
   virtual bool getAppParameters( MvRequest&, ApplicationInfo& ) = 0;

   // Set flags
   virtual void setHorCompFlags( bool, bool, bool ) {}

   // Check that this field's vital statistics match those of the others
   // - this is important only in the Average application
   virtual bool fieldConsistencyCheck( MvField&, double, double, double, double ) { return true; }

   // Check this field's geographical grid point positions against the user input
   // grid point postion. This is important only in the Vertical Profile application
   virtual bool fieldConsistencyCheck ( MvField&, ApplicationInfo& ) { return true; }

   // Get default variable to be plotted
   virtual ParamInfo* plotVariable ( ApplicationInfo&, ParamMap& );

   // Get netCDF variable name
   virtual string getNetcdfVarname( const string& );

   // Get netCDF level variable name
   virtual string getNetcdfLevelVarname(string& varname)
      { return varname + "_lev"; }

   // Get netCDF Value and Components variable names
   virtual string getNetcdfValueVarname()      { return "value";       }
   virtual string getNetcdfXComponentVarname() { return "x_component"; }
   virtual string getNetcdfYComponentVarname() { return "y_component"; }

   // Get/create a netCDF variable
   virtual MvNcVar* getNetcdfVariable( MvNetCDF&, const string&v, ApplicationInfo&, const string&, ParamInfo*);
   virtual MvNcVar* getNetcdfVariableLevel( MvNetCDF&, const string&v, ApplicationInfo& );

   // Check if data module was dropped
   bool isDataModuleDropped( const char* );

   // Free memory
   void deleteAuxiliaryMemory(double*, ParamMap&);

   // Add information to help the Macro Converter to translate
   // the output request to a Macro code
   MvRequest buildMacroConverterRequest();


   // get and set geoIndexVar_
   void setGeoIndexVar(const std::string &var) {geoIndexVar_ = var;}
   std::string getGeoIndexVar() {return geoIndexVar_;}


   // Variables
   MvRequest origReq_; // input request
   string type_;       // application type: MVPROFILE, MXSECTION, MXAVERAGE
   string view_;       // application view: MVPROFILEVIEW, MXSECTIONVIEW, MXAVERAGEVIEW
   string ncName_;     // netCDF file name
   int ntime_;         // time counter. It assumes that the input data is sorted
                       // by variable and time, e.g. v1t1, v1t2, .. vntm, v2t1, ...
   string geoIndexVar_; // the last dimension in the 'value' variable (lat/lon)
};

#endif
