/***************************** 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 HOVTOOLKIT_H
#define HOVTOOLKIT_H

#include "Factory.h"
#include "MvHovmFrame.h"
#include "MvNetCDF.h"

enum { HOV_TIME, HOV_GEO };           //vertical axis: time or 'second' axis
enum { HOV_NS, HOV_EW };              //average direction: North-South or East-West
enum { HOV_ASINDATA, HOV_PRESSURE };  //height axis type options

const string HOV_VARLEVEL   = "nlev";
const string HOV_VARTIME    = "time";
const string HOV_VARLAT     = "lat";
const string HOV_VARLON     = "lon";

class HovToolkit {

public:

   HovToolkit();
   virtual ~HovToolkit();

   // Release memory
   void ReleaseAllMemory();
   void ReleaseMemory();
   void ReleaseMemoryParam();

   // Initialise internal variables
   bool GetInputParameters( MvRequest& );
   virtual bool GetInputInfo(MvRequest&) = 0;
   bool GetInputCommonInfo(MvRequest&);       //from user interface
   virtual bool GetInputInfo(MvNetCDF*) = 0;
   bool GetInputCommonInfo(MvNetCDF*);        //from the netcdf file

   // Compute Hovmoeller diagram (main routine)
   // Create a new netcdf file
   virtual bool Compute(MvRequest&,MvRequest&);

   // Compute Hovmoeller diagram (main routine)
   // Expand a existing netcdf file
   virtual bool Compute(string&,MvRequest&,string,MvRequest&);

   // Handle creating variables, data and file
   virtual bool ComputeValues(MvField&, int=0) = 0;
   virtual bool GenerateData(MvRequest&);
   virtual bool Initialiser();

   // Create output request using information from the application
   MvRequest CreateOutputRequest();

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

   // Create View request
   virtual MvRequest CreateViewRequest() = 0;

   // Initialize Param Info structure
   bool CreateParamInfo(MvRequest&);

   // Create access keys
   virtual void GenerateKey(string&, MvRequest&);
   void GenerateTimeKey(string&, MvRequest&);

   // Access time/date information
   double GetRefTime() { return refTime_; }
   void   SetRefTime( double ref ) { refTime_ = ref; }
   MvDate GetDate( MvField& );
   double GetDateDif( string& );
   bool   GetTimeInfo();
   void   GetTimeInfoFromParam();

   // Handle number of points of the second coordinates
   int NPoints() { return nrPoints_; }
   void NPoints( int size ) { nrPoints_ = size; }

   // Handle number of indexes
   int NrIndexes() { return nrIndexes_; }

   // Functions to handle list of levels
   virtual void InitializeLevelList () { }
   virtual void UpdateLevelList (MvField&,double) { }

   // Functions to handle the netcdf file
   bool NcAddCommonVariables();
   bool NcWriteData(MvField&, const string& key);
   void NcAddMetadata(MvNcVar*, ParamInfo*);
   string getNetcdfVarname(string); // Get netCDF variable name
   virtual string GetTitle(ParamInfo*) = 0;
   virtual const char* ApplicationType() = 0;
   virtual void NcWriteGlobalAttributes();
   virtual void NcWriteGlobalAttributesApp() = 0;
   virtual bool NcWriteTimeInfo();
   virtual bool NcWriteSecondCoord() = 0;

   // Update output matrix of values
   void NcFillValues(MvNcVar*, ParamInfo*);
   void NcWriteValues (MvNcVar*, IndexesInfo*, int);

   // Functions to handle the Expand option
   void ExpandOpenNcFile();
   void ExpandCloseNcFile();
   void ExpandFillValues(MvNcVar*, int&);
   bool ExpandFillValues(const char*, int, vector<double>&);
   bool ExpandGetTimeInfo();

   MvRequest GetVariableData(MvRequest&);
   void InitializeAxes(MvRequest&);

   // Functions to handle axes parameters
   virtual const char* GetSecondCoordName() = 0;  // the first axis name is "time"
   virtual const char* GetSecondAuxiliaryCoordName() { return " "; }
   virtual bool SecondAuxiliaryCoord() = 0;
   virtual bool ComputeSecondCoord() = 0;
   virtual string GeolineConvention() { return glConvention_; }

   // Functions to handle action mode
   void ActionMode( string action ) { actionMode_ = action; }
   string ActionMode() { return actionMode_; }
   bool IsVisualise();
   bool IsDataModule(const char*);

   // Get Parameter info given the key
   ParamInfo* GetParamInfo( const string& );

   // Get application view
   MvRequest GetAppView ( MvRequest& );

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

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

protected:

   bool swapAxes_;                  // swap default axes
   int procType_;                   // process type
   int verticalAxis_;               // Time axis or Geo axis
   int nrPoints_;                   // number of points of the second axis
   int nrIndexes_;                  // number of points of the time axis
   double x1_, x2_, y1_, y2_;       // geographical coordinates
   double gridNS_, gridEW_;         // grid interval
   double refTime_;                 // reference Time value
   double dateMinD_,dateMaxD_;      // min/max date values
   string ncdfPath_;                // netCDF file path
   string actionMode_;              // "examine"/"save"/"execute"/...
   string glConvention_;            // geoline convention: lonlat or latlon
   MvNetCDF *netcdf_;               // netcdf structure
   MvRequest dataRequest_;          // grib data
   MvRequest origReq_;              // original input request

   // Variables related to Param info and values
   double* xint_;                   // point values
   vector<double> coord1_;          // second coordinate values (lat/lng/level)
   vector<double> coord2_;          // second coordinate values (lat/lng)
   vector<double> vtime_;           // time values
   ParamMap params_;                // structure holding computed values

   // Variables related to the Expand option
   bool expand_;                    // true: expand option
   int nrIndexesIn_;                // number of initial time points
   string netfnameIn_;              // input netcdf filename
   MvNetCDF *netcdfIn_;             // Input netcdf structure
};

#endif
