///////////////////////////////////////////////////////////
//                                                       //
//                         SAGA                          //
//                                                       //
//      System for Automated Geoscientific Analyses      //
//                                                       //
//                    Module Library:                    //
//                          GR4J                         //
//                                                       //
//-------------------------------------------------------//
//                                                       //
//                      gr4j_cal.h                       //
//                                                       //
//                 Copyright (C) 2007 by                 //
//                     Stefan Liersch                    //
//-------------------------------------------------------//
//                                                       //
//    e-mail:     stefan.liersch@ufz.de                  //
//                stliersch@freenet.de                   //
//                                                       //
//                     2007-03-08                        //
//                                                       //
///////////////////////////////////////////////////////////


//*******************************************************//
//                        ToDo                           //
//-------------------------------------------------------//
// - include different objective functions for calibration
// - check parameter ranges in Dialog1
// - write 5 best simulations in output table
// - introduce warm-up period
//*******************************************************//

//---------------------------------------------------------
#ifndef HEADER_INCLUDED__gr4j_cal_H
#define HEADER_INCLUDED__gr4j_cal_H

//---------------------------------------------------------
#include "MLB_Interface.h"
#include "gr4j_cal.h"
#include "gr4j.h"
#include "pet_sl.h"
#include "snow_module.h"

#include <vector>   // used for storing date string values in a vector
using namespace std;

typedef std::vector<std::string> date_array;
typedef vector<double> vector_d;
//---------------------------------------------------------

struct Q_sim_out {
	double* Q_sim;
};

class Cgr4j_cal : public CSG_Module
{
public:

	// constructor
	Cgr4j_cal(void);

	// destructor
	virtual ~Cgr4j_cal(void);

protected:

	// execute module
	virtual bool		On_Execute			(void);

private:

	//---------------------------------------------------------------

	int					sizeAll;	// number of values in selected period
	double*				temperature; // used if no ETp data are available

	//-------------------------------------------
	// Parameters of dialog 1
	//-------------------------------------------
	int					m_nsim;		// number of simulations
	int					m_nbestsim; // number of best simulations for output table
	int					m_bestsimcount;
	int					m_nsim_snow;	// number of simulations for snow module

	bool				m_bSnowModule;

	double				m_NSE_MIN;	 // minimum Nash-Sutcliffe Efficiency for output
	int*				m_TopNSE;
	// struct GR4J_Parameters defined in 'gr4j.h'
	GR4J_Parameters*	X;		// used in Monte Carlo simulation
	GR4J_Parameters		X_lb;	// lower bounds
	GR4J_Parameters		X_ub;	// upper bounds
	//-------------------------------------------

	//-------------------------------------------
	// Parameters of dialog 1
	//-------------------------------------------
	double				m_area;	// river basin area [km2]
	//-------------------------------------------

	// snow module parameters
	double				*mT_Rain;
	double				*mT_Melt;
	double				*mDD_FAC;
	double				mT_Rain_lb;
	double				mT_Rain_ub;
	double				mT_Melt_lb;
	double				mT_Melt_ub;
	double				mDD_FAC_lb;
	double				mDD_FAC_ub;
	int					*m_pTopNSE_SNOW; // Nash-Sutcliffe Efficiency

	Q_sim_out			*m_pQ_sim_best;

	// struct InputData defined in 'gr4j.h'
	InputData			Input;

	double				*m_pNSE;		// Nash-Sutcliffe Efficiency
	double				*m_pNSE_SNOW;	// Nash-Sutcliffe Efficiency (using snow module)
	double				*m_pNSE_highflow;// Nash-Sutcliffe Efficiency adapted to high flow

	// Class Cgr4j containing GR4J equations
	Cgr4j				gr4j;
	Cgr4j				*pgr4j;

	// Class CpET is used to calculate ETp from a temperature time series
	CpET*				ETp;

	// Class CSnowModule
	CSnowModule			*pSnowModule;
	
	void				_Simulate(double NSE_min);
	void				_Find_BestSimulations(int nbestsim);
	void				_Calibrate_SnowModule();
	void				_Calc_BestSimulationsSnow();
	void				_Calc_BestSimulationsNoSnow();

	// Initialize Input arrays and calculate ETp from temperature if necessary
	void				_InitInput(InputData& Input, int sizeAll, int Choice_ETp_TMP,
									double area, double Latitude, CSG_Table* pTable, int dateField, int dischargeField,
									int pcpField, int pet_tmpField,
									int first, int last);

	// Create SAGA output table containing Nash-Sutcliffe efficiency
	// and parameter settings
	void				_CreateTableCal(CSG_Table *pTable,
										GR4J_Parameters* X,
										double* NSE, double* NSE_highflow, double NSE_MIN,
										int nsim);
	// using this function if snow module is active
	void				_CreateTableCal(CSG_Table *pTable,
										GR4J_Parameters* X,
										double* NSE, double* NSE_highflow, double NSE_MIN,
										int nsim,
										double t_rain,double t_melt, double dd_fac);

	void				_CreateTableSim(CSG_Table *pTable,
										int nbestsim,
										InputData Input,
										Q_sim_out *Q_sim_best,
										int sizeAll, double area);

	void				_CreateTableSnow(CSG_Table *pTable,
										int nbestsim, // *2
										InputData Input,
										Q_sim_out *Q_sim_best,
										int sizeAll, double area);

	void				_CreateTableSnowParms(CSG_Table *pTable,
											  int nsim, double *NSE_SNOW,
											  double *t_rain,double *t_melt, double *dd_fac);

	//---------------------------------------------------------------------
	//		HELPER FUNCTIONS
	//---------------------------------------------------------------------
	// Converting a date string 'YYYYMMDD' to three separate integer values
	void				_Get_Date_Int(string date, int &year, int &month, int &day);

	// Create the user dialogs
	void				_CreateDialog1();
	bool				_CreateDialog2(CSG_Table* pTable, int dateField,
									   CSG_String& date1, CSG_String& date2,
									   int Choice_ETp_TMP, bool bSnowModule,
									   double& Latitude, double& area);

};

#endif /* __gr4j_cal_H */