///////////////////////////////////////////////////////////
//                                                       //
//                         SAGA                          //
//                                                       //
//      System for Automated Geoscientific Analyses      //
//                                                       //
//                    Module Library:                    //
//                        IHACRES                        //
//                                                       //
//-------------------------------------------------------//
//                                                       //
//                    ihacres_cal.h                      //
//                                                       //
//                 Copyright (C) 2006 by                 //
//                     Stefan Liersch                    //
//-------------------------------------------------------//
//                                                       //
//    e-mail:     stefan.liersch@ufz.de                  //
//                stefan.liersch@gmail.com                   //
//                                                       //
//                     2006-07-26                        //
//                                                       //
///////////////////////////////////////////////////////////


//*******************************************************//
//                        ToDo                           //
//-------------------------------------------------------//
// - Simulate Streamflow for
//   - single storage noch nicht fertig!!!
//   - two or more storages in series
// - implement 2 or n storages in series
// - implement single storage correctly
// - number of simulations for linear module
// - choosing the number of Top simulations from non-linear module calibration
// - Gültigkeitsbereiche auf Sinn prüfen
// - WriteTable1Storage
// - Streamflow simulation function using n, m values
// - if (bTMP) = false ???
// - bei mehrmaligem starten, stürzt Modul ab,
//   wahrscheinlich aufgrund irgendwelcher arrays
//
// - Dialog:
//		- move non-linear parameters from first to second dialog
//		- aggregate model config (storage config, IHAC version, snow module) under one node in dlg1
// - Output tables
//		- give tables a unique name: build name from input file and a number
//		- p und l ausgeben
//		-verwendete Version ausgeben
// - Delete pointers
//		- snow module
//		- Croke parameters l and p
//*******************************************************//

//---------------------------------------------------------
#ifndef HEADER_INCLUDED__ihacres_cal_H
#define HEADER_INCLUDED__ihacres_cal_H
//---------------------------------------------------------

#include "MLB_Interface.h"
#include "ihacres_eq.h"

#include <vector>   // used for storing date string values in array
using namespace std;
typedef std::vector<std::string>	date_array;
typedef std::vector<double>			vector_d;
typedef std::vector<int>			vector_i;
typedef std::vector<bool>			vector_b;
//---------------------------------------------------------

struct S_IHAC_parms_for_snowmod_Cal
{
	// This struct is used to calibrate the snow module
	// non-linear module parms
	double		tw;
	double		f;
	double		c;
	double		l;
	double		p;
	// index of the non-linear settings of 
	// Top 5 simulations
	int			nl_index;
	// linear parms
	double		a;	// single storage
	double		b;
	double		aq;	// two storages
	double		as;
	double		bq;
	double		bs;
	int			delay;
};
//---------------------------------------------------------

class Cihacres_cal : public CSG_Module
{
public:

	// constructor
	Cihacres_cal(void);

	// destructor
	virtual ~Cihacres_cal(void);

protected:

	// execute module
	virtual bool	On_Execute		(void);

private:

	//--------------------------------------------------------
	// Private Member Variables
	//--------------------------------------------------------
	int				m_counter;		// used in _WriteTable2Parallel and WriteTable1Storage

	int				m_sizeAll;		// array size (number of records in input data)

	date_array		m_vec_date;		// Vector containing date values
	double*			m_p_Q_obs_m3s;	// Array containing observed discharge values in [m3/s]
	double*			m_p_Q_obs_mmday;// Array containing observed discharge values in [mm]
	double*			m_pPCP;			// Array containing observed precipitation values		
	double*			m_pTMP;			// Array containing temperature values
	double*			m_pTw;			// Tw is approximately the time constant, or inversely,
									// the rate at which the catchment wetness declines
									// in the absence of rainfall.
	double*			m_pWI;			// catchment wetness index
	
	double*			m_pExcessRain;	// "excess" or effective rainfall [mm]
	
	double*			m_pQ_sim_m3s;	// simulated streamflow [m3/s]
	double*			m_pQ_sim_mmday;

	double*			m_pSum_eRainMM;	// sum of estimated effective rainfall [mm]
	

	bool*			m_p_bValidSim;	// if a simulation seems to have logical parameter settings,
									// the simulation is true, otherwise false
									// logical settings depend on differences between
									// estimated volumes of excess rain and streamflow, and
									// on the amount of "cutted" excess rainfall
	
	double			m_sum_obsDisMM;	// sum of observed discharge in [mm]
	double			m_sum_eRainGTpcp;// sum of excess rainfall that is greater
									// than precipitation in one simulation
	double			m_vq;			// fraction of quick flow
	double			m_vs;			// fraction of slow flow

	// variables from function On_Execute
	CSG_String		m_date1, m_date2; // first and last date of selected period

	double			m_NSEmin;		// minimum NSE required to print in calibration table
	int				m_obj_func;		// objective function for calibration

	// non linear module parameters
	double			m_TwConst_ub;	// Tw is approximately the time constant, or inversely,
	double			m_TwConst_lb;	// the rate at which the catchment wetness declines
									// in the absence of rainfall.
	double			m_f_lb;			// temperature modulation factor which
	double			m_f_ub;			// determines how Tw changes with temperature
	double			m_c_lb;			// Parameter c is chosen so that the volume
	double			m_c_ub;			// of excess rainfall is equal to the total
									// streamflow over the calibration period
	// Croke et al. (2005) Redesign of non-linear module
	double			m_l_lb;			// soil moisture index threshold
	double			m_l_ub;
	double			m_p_lb;			// power on soil moisture
	double			m_p_ub;

	// linear module parameters (single storage)
	double			m_a_lb;
	double			m_a_ub;
	double			m_b_lb;
	double			m_b_ub;
	// linear module parameters (2 storages)
	double			m_aq_lb;
	double			m_aq_ub;
	double			m_as_lb;
	double			m_as_ub;
	double			m_bq_lb;
	double			m_bq_ub;

	int				m_delay;		// The delay after the start of rainfall,
									// before the discharge starts to rise.

	int				m_nsim;			// number of simulations
	double			m_area;			// area of the watershed in [km2]

	// random parameters (calibration)
	// non-linear module
	C_IHAC_NonLinearParms*	m_pNLP_top;
	C_IHAC_NonLinearParms*	m_pNLP_random;

	// random parameters (calibration)
	// linear module
	C_IHAC_LinearParms*		m_pLP_random;

	//--------------------------------------------------------
	// snow module parameters
	//--------------------------------------------------------
	// class CSnowModule (snow_module.h/.cpp)
	CSnowModule*	m_pSnowModule;
	bool			m_bSnowModule;// if bSnowModule = true, snow module is active
	double*			m_pMeltRate;
	// SnowModule calibration parameters
	double			m_T_Rain_lb;
	double			m_T_Rain_ub;
	double			m_T_Melt_lb;
	double			m_T_Melt_ub;
	double			m_DD_FAC_lb;
	double			m_DD_FAC_ub;
	double*			m_pT_Rain_rand;
	double*			m_pT_Melt_rand;
	double*			m_pDD_FAC_rand;
	S_IHAC_parms_for_snowmod_Cal m_snowcal_parms;
	//--------------------------------------------------------

	//--------------------------------------------------------
	// Private Member Functions
	//--------------------------------------------------------

	void			_ZeroVariables			();
	void			_InitArrays_sizeAll		(int size, bool bSnowModule);
	void			_InitArrays_nsim		(int nsim, bool bSnowModule);

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

	void			_CalcNonLinearModule	(bool bTMP, int IHAC_version, bool bSnowModule,
											 int nsim,
											 double dev_eRainDis,
											 double dev_eRainPCP);

	// Used in linear module calibration only
	void			_RunNonLinearModule		(bool TMP_data_exist, int IHAC_version,
											 double *p_TMP, double *p_PCP, int size,
											 C_IHAC_NonLinearParms *nl_parms, int j,
											 double *p_ExcessRain, bool dummy_bSnowModule);

	void			_Get_Best_NonLinear_Sims(int nTopSims, int &nTop, int IHAC_version);

	void			_CalcLinearModule		(bool bTMP, int IHAC_version, int storconf, bool bSnowModule,
											 int nTop, CSG_Table &pTable);
	//--------------------------------------------------------

	// create output table
	void			_CreateTableCal			(CSG_Table *pTable_out, int IHAC_version, bool bSnowModule,
											 C_IHAC_NonLinearParms* nl_parms,
											 int size);

	// create output table (simulation parameters)
	void			_CreateTable2Parallel	(CSG_Table *pTable_parms, bool bSnowModule);
	void			_CreateTable1Storage	(CSG_Table *pTable_parms, bool bSnowModule);

	// write data into table Parms2Parallel
	void			_WriteTable2Parallel	(CSG_Table *pTable_parms, bool bSnowModule,
											 double NSE, double NSE_high, double NSE_low, double eR,
											 double vq, double vs,
											 double Tw, double f, double c,
											 double T_Rain, double T_Melt, double DD_Fac,
											 double aq, double as,
											 double bq, double bs);

	void			_WriteTable1Storage		(CSG_Table *pTable_parms, bool bSnowModule,
											 double NSE, double eR,
											 double Tw, double f, double c,
											 double T_Rain, double T_Melt, double DD_Fac,
											 double a, double b);
	//--------------------------------------------------------

	// Random number function
	double			_Random_double			(double lb, double ub);

	// Count number of true values in a bool array
	int				_CountNumberTrue		(bool *array, int size);

	// Find the indices of simulations with best parameter settings
	// depending on the lowest differences of
	// estimated excess rainfall and observed discharge
	void			_FindTopIndex			(double *array, int ntrue,
											 int *TopIndex, int top);

	// Find the simulation with the best fit (Nash-Sutcliffe Efficiency)
	void			_FindTopNSE				(double *array, int size,
											 int *TopNSE, int top);

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

	void			_CreateDialog1			();

	bool			_CreateDialog2			(bool bTMP, bool bnl_only,
											 int storconf,
											 int IHAC_version,
											 bool bSnowModule,
											 CSG_Table *pTable,
											 int dateField,
											 int dischargeField);

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

	// class Cihacres_eq, in order to use functions from this class
	Cihacres_eq		ihac;
};

//---------------------------------------------------------
#endif /* #ifndef HEADER_INCLUDED__ihacres_cal_H */