///////////////////////////////////////////////////////////
//                                                       //
//                         SAGA                          //
//                                                       //
//      System for Automated Geoscientific Analyses      //
//                                                       //
//                    Module Library:                    //
//                      ihacres_v1                       //
//                                                       //
//-------------------------------------------------------//
//                                                       //
//                    ihacres_v1.cpp                     //
//                                                       //
//                 Copyright (C) 2006 by                 //
//                     Stefan Liersch                    //
//-------------------------------------------------------//
//                                                       //
//    e-mail:     stefan.liersch@ufz.de                  //
//                stefan.liersch@gmail.com                   //
//                                                       //
//                     2006-08-31                        //
//-------------------------------------------------------//
//                                                       
// References:											 
// Jakeman, A.J. / Hornberger, G.M (1993).				 
//   How Much Complexity Is Warranted in a				 
//	 Rainfall-Runoff Model?								 
//	 Water Resources Research, (29), NO. 8 (2637-2649)   
// Kokkonen, T. S. et al. (2003).
//   Predicting daily flows in ungauged catchments:
//   model regionalization from catchment descriptors
//   at the Coweeta Hydrologic Laboratory, North Carolina
//   Hydrological Processes (17), 2219-2238
// Croke, B. F. W., W. S. Merritt, et al. (2004).
//   A dynamic model for predicting hydrologic response
//   to land cover changes in gauged and
//   ungauged catchments.
//   Journal Of Hydrology 291(1-2): 115-131.
//-------------------------------------------------------//

//---------------------------------------------------------
#include <iostream> // used for textfile output (test only)
#include <fstream>  // used for textfile output (test only)

#include "ihacres_v1.h"
#include "ihacres_cal.h"
#include ".\..\model_tools.h"
//---------------------------------------------------------

// constructor
Cihacres_v1::Cihacres_v1(void)
{
	//-----------------------------------------------------
	// 1. Info...
	Set_Name("IHACRES Version 1.0");

	Set_Author("copyrights (c) 2006 Stefan Liersch");

	Set_Description("The Rainfall-Runoff Model IHACRES \n \n \n"
		"Reference: \n \n"
		"Jakeman, A.J. / Hornberger, G.M. (1993). \n"
		"How Much Complexity Is Warranted in a Rainfall-Runoff Model? \n"
		"Water Resources Research, (29), NO. 8 (2637-2649) \n \n"   
		"Kokkonen, T. S. et al. (2003). \n"
		"Predicting daily flows in ungauged catchments:"
		"model regionalization from catchment descriptors"
		"at the Coweeta Hydrologic Laboratory, North Carolina \n "
		"Hydrological Processes (17), 2219-2238 \n \n"
		"Croke, B. F. W., W. S. Merritt, et al. (2004).\n"
		"A dynamic model for predicting hydrologic response"
		"to land cover changes in gauged and"
		"ungauged catchments. \n"
		"Journal Of Hydrology 291(1-2): 115-131."
	);

	///////////////////////////////////////////////////////////////////
	// FIRST MODULE DIALOG
	CreateDialog1();
	///////////////////////////////////////////////////////////////////
}

//---------------------------------------------------------
// destructor
Cihacres_v1::~Cihacres_v1(void)
{}

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

bool Cihacres_v1::On_Execute(void)
{
	///////////////////////////////////////////////////////////////////
	//
	//								VARIABLES
	//
	///////////////////////////////////////////////////////////////////
	int				j,k;		//counter
	CSG_Table		*pTable, *pTable_out, *pTable_parms, *pTable_settings;

	bool			bTMP;		// true, if temperature data are used to
								// to refine wetness index estimation.
	bool			writeAllTimeSeries;
	int				storconf;	// storage configuration
								// 0 = single, 1 = two parallel, 2 = two in series

	// Assign Parameters from first Module Dialog
	//---------------------------------------------------------
	pTable			= Parameters("TABLE")			->asTable();
	// Field numbers
	dateField		= Parameters("DATE_Field")		->asInt();
	dischargeField	= Parameters("DISCHARGE_Field")	->asInt();
	pcpField		= Parameters("PCP_Field")		->asInt();
	tmpField		= Parameters("TMP_Field")		->asInt();

	bTMP			= Parameters("USE_TMP")			->asBool();
	c				= Parameters("CFAC")			->asDouble();
	TwConst			= Parameters("TwFAC")			->asDouble();
	m_area			= Parameters("AREA")			->asDouble();
	storconf		= Parameters("STORAGE")			->asInt();
	IHAC_version	= Parameters("IHACVERS")		->asInt();
	bSnowModule		= Parameters("SNOW_MODULE")		->asBool();
	writeAllTimeSeries = Parameters("WRITEALL_TS")	->asBool();
	first = last	= 0;
	//---------------------------------------------------------

	///////////////////////////////////////////////////////////////////
	// Create Second Dialog and assign linear module parameters
	CreateDialog2(bTMP, storconf, IHAC_version, pTable, dateField, dischargeField);
	///////////////////////////////////////////////////////////////////

	///////////////////////////////////////////////////////////////
	// searching the first and the last record of the time range
	ihacres->AssignFirstLastRec(*pTable, first, last, date1, date2, dateField);
	///////////////////////////////////////////////////////////////

	///////////////////////////////////////////////////////////////
	//					INITIALIZE VECTORS
	sizeAll = last - first + 1;
	// global array variables
	date.resize(sizeAll);
	m_Q_obs_m3s.resize(sizeAll);
	m_Q_obs_mmday.resize(sizeAll);
	precipitation.resize(sizeAll);
	if (bTMP) temperature.resize(sizeAll);

	for (j = 0, k = first; j < sizeAll, k < last + 1; j++, k++)
	{
		date[j].append(pTable->Get_Record(k)->asString(dateField));
		m_Q_obs_m3s[j]			 = pTable->Get_Record(k)->asDouble(dischargeField);
		precipitation[j]		 = pTable->Get_Record(k)->asDouble(pcpField);
		if (bTMP) temperature[j] = pTable->Get_Record(k)->asDouble(tmpField);
	}

	if (bSnowModule && bTMP)
	{
		m_pSnowModule = new CSnowModule(temperature, precipitation, T_Rain, T_Melt, DD_FAC);
		if (!bSnowModule) m_pSnowModule = NULL;
		//m_pSnowModule->MeltRate = new double[sizeAll];
		//m_pSnowModule->SnowStorage = new double[sizeAll];
	}

	//---------------------------------------------------------
	// Convert streamflow from m3/s to mm/day
	///////////////////////////////////////////////////////////////


	///////////////////////////////////////////////////////////////
	//
	//					INSTANTIATE CLASS IHACRES
	//
	///////////////////////////////////////////////////////////////

	// different constructors are available for class ihacres_eq,
	// depending on availability of temperature data,
	// storage characteristics, and data storage properties (vector / arrays)

	switch(storconf)
	{
	case 0: // single storage
		ihacres = new Cihacres_eq(date,
								  m_Q_obs_m3s,
								  precipitation,
								  temperature,
								  TwConst, f, c,
								  a, 0, b, 0,
								  m_area,
								  bTMP,
								  IHAC_version,
								  storconf,
								  bSnowModule,
								  m_pSnowModule,
								  delay);
		break;
	case 1: // two storages in parallel
		// if temperature data available
		// and using vectors to store time series data
		// and 2 storages in parallel
		ihacres = new Cihacres_eq(date,
								  m_Q_obs_m3s,
								  precipitation,
								  temperature,
								  TwConst, f, c,
								  aq, as, bq, bs,
								  m_area,
								  bTMP,
								  IHAC_version,
								  storconf,
								  bSnowModule,
								  m_pSnowModule,
								  delay);
		break;
	} // end switch

	//---------------------------------------------------------
	// create output tables and add them to SAGA workspace
	//---------------------------------------------------------
	pTable_out   = SG_Create_Table();
	CreateTableSim(pTable_out, date, m_Q_obs_m3s, ihacres->get_streamflow_sim());//ihacres->streamflow_sim);
	// add tables to SAGA Workspace
	pTable_out->Set_Name("IHACRES_Sim");
	Parameters("TABLEout")->Set_Value(pTable_out);
		
	pTable_settings   = SG_Create_Table();
	if (bSnowModule)
	{
		CreateTableSettings(pTable_settings, TwConst, c, f, aq, as, bq, bs,
							ihacres->get_vq(), ihacres->get_vs(),
							bSnowModule, m_pSnowModule->Get_T_Rain(), m_pSnowModule->Get_T_Melt(), m_pSnowModule->Get_DD_FAC(),
							delay,
							model_tools::CalcRunoffCoeff(m_Q_obs_mmday,precipitation), ihacres->get_NSE(),
							m_area);
	} else {
		CreateTableSettings(pTable_settings, TwConst, c, f, aq, as, bq, bs,
							ihacres->get_vq(), ihacres->get_vs(),
							bSnowModule, 0, 0, 0,
							delay,
							model_tools::CalcRunoffCoeff(m_Q_obs_mmday,precipitation), ihacres->get_NSE(),
							m_area);
	}
	pTable_settings->Set_Name("IHACRES_Settings");
	Parameters("TABLEsettings")->Set_Value(pTable_settings);

	if (writeAllTimeSeries)
	{
		pTable_parms = SG_Create_Table();
		CreateTableParms(pTable_parms, date, m_Q_obs_m3s, precipitation, temperature,
						ihacres->get_streamflow_sim(), ihacres->get_excessRain(),
						ihacres->get_WetnessIndex(), ihacres->get_Tw());
		pTable_parms->Set_Name("IHACRES_Parms");
		Parameters("TABLEparms")->Set_Value(pTable_parms);
	}

	///////////////////////////////////////////////////////////////
	//						DELETE AND RESIZE
	///////////////////////////////////////////////////////////////
	delete ihacres;
	date.resize(0);
	m_Q_obs_m3s.resize(0);
	m_Q_obs_mmday.resize(0);
	precipitation.resize(0);
	if (bTMP) temperature.resize(0);
	if (bSnowModule) delete m_pSnowModule;
	///////////////////////////////////////////////////////////////

	//---------------------------------------------------------
	return( true );   // bool Cihacres_cal::On_Execute(void)
} // end function On_Execute()


///////////////////////////////////////////////////////////////////////
//
//                          PRIVATE FUNCTIONS
//
///////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////
//
//                          CREATE OUTPUT TABLES
//
///////////////////////////////////////////////////////////////////////

void Cihacres_v1::CreateTableSim(CSG_Table *pTable, date_array date, vector_d strfl_obs, vector_d strfl_sim)
{
	int i = 0; // used in function Get_Record(i)
	CSG_Table_Record	*pRecord;

	// creating the column titles
	pTable->Add_Field("Date",		TABLE_FIELDTYPE_String);
	pTable->Add_Field("Flow OBS",	TABLE_FIELDTYPE_Double);
	pTable->Add_Field("Flow SIM",	TABLE_FIELDTYPE_Double);

	for (unsigned int j = 0; j < date.size(); j++)
	{
		pTable->Add_Record();
		pRecord = pTable->Get_Record(i);

		// writing the data into the rows
		pRecord->Set_Value(0,date[j].c_str());
		pRecord->Set_Value(1,strfl_obs[j]);
		pRecord->Set_Value(2,model_tools::mmday_to_m3s(strfl_sim[j],m_area));
		i++;
	}
}

void Cihacres_v1::CreateTableParms(CSG_Table *pTable, date_array date, vector_d strfl_obs, vector_d precipitation, vector_d temperature,
								   vector_d strfl_sim, vector_d excessRain, vector_d wi, vector_d Tw)
{
	int i = 0; // used in function Get_Record(i)
	CSG_Table_Record	*pRecord;

	// creating the column titles
	pTable->Add_Field("Date",			TABLE_FIELDTYPE_String);
	pTable->Add_Field("Flow OBS",		TABLE_FIELDTYPE_Double);
	pTable->Add_Field("Flow SIM",		TABLE_FIELDTYPE_Double);
	pTable->Add_Field("TMP",			TABLE_FIELDTYPE_Double);
	pTable->Add_Field("PCP",			TABLE_FIELDTYPE_Double);
	pTable->Add_Field("ExcessRain",		TABLE_FIELDTYPE_Double);
	pTable->Add_Field("WetnessIndex",	TABLE_FIELDTYPE_Double);
	pTable->Add_Field("Tau",			TABLE_FIELDTYPE_Double);

	for (unsigned int j = 0; j < date.size(); j++)
	{
		pTable->Add_Record();
		pRecord = pTable->Get_Record(i);

		// writing the data into the rows
		pRecord->Set_Value(0,date[j].c_str());
		pRecord->Set_Value(1,strfl_obs[j]);
		pRecord->Set_Value(2,model_tools::mmday_to_m3s(strfl_sim[j], m_area));
		pRecord->Set_Value(3,temperature[j]);
		pRecord->Set_Value(4,precipitation[j]);
		pRecord->Set_Value(5,excessRain[j]);
		pRecord->Set_Value(6,wi[j]);
		pRecord->Set_Value(7,Tw[j]);
		i++;
	}
}

void Cihacres_v1::CreateTableSettings(CSG_Table *pTable, double Tw, double c, double f,
									  double aq, double as, double bq, double bs,
									  double vq , double vs,
									  bool bSnowModule, double T_Rain, double T_Melt, double DD_FAC,
									  int delay,
									  double RRCoef, double NSE,
									  double m_area)
{
	int count = 1;
	CSG_Table_Record	*pRecord;

	// creating the column titles
	pTable->Add_Field("Parameters",	TABLE_FIELDTYPE_String);
	pTable->Add_Field("Settings",	TABLE_FIELDTYPE_Double);

	pTable->Add_Record();
	pRecord = pTable->Get_Record(0);
	pRecord->Set_Value(0,"Tau");
	pRecord->Set_Value(1,Tw);	

	pTable->Add_Record();
	pRecord = pTable->Get_Record(1);
	pRecord->Set_Value(0,"c");
	pRecord->Set_Value(1,c);	

	pTable->Add_Record();
	pRecord = pTable->Get_Record(2);
	pRecord->Set_Value(0,"f");
	pRecord->Set_Value(1,f);

	pTable->Add_Record();
	pRecord = pTable->Get_Record(3);
	pRecord->Set_Value(0,"a(q)");
	pRecord->Set_Value(1,aq);

	pTable->Add_Record();
	pRecord = pTable->Get_Record(4);
	pRecord->Set_Value(0,"a(s)");
	pRecord->Set_Value(1,as);

	pTable->Add_Record();
	pRecord = pTable->Get_Record(5);
	pRecord->Set_Value(0,"b(q)");
	pRecord->Set_Value(1,bq);

	pTable->Add_Record();
	pRecord = pTable->Get_Record(6);
	pRecord->Set_Value(0,"b(s)");
	pRecord->Set_Value(1,bs);
	//pRecord->Set_Value(1,vs * (1 + as));

	pTable->Add_Record();
	pRecord = pTable->Get_Record(7);
	pRecord->Set_Value(0,"v(q)");
	pRecord->Set_Value(1,vq);

	pTable->Add_Record();
	pRecord = pTable->Get_Record(8);
	pRecord->Set_Value(0,"v(s)");
	pRecord->Set_Value(1,vs);

	pTable->Add_Record();
	pRecord= pTable->Get_Record(9);
	pRecord->Set_Value(0,"T(q)");
	pRecord->Set_Value(1,ihacres->Calc_TimeOfDecay(aq));

	pTable->Add_Record();
	pRecord= pTable->Get_Record(10);
	pRecord->Set_Value(0,"T(s)");
	pRecord->Set_Value(1,ihacres->Calc_TimeOfDecay(as));

	if (bSnowModule)
	{
		pTable->Add_Record();
		pRecord = pTable->Get_Record(10+count);
		pRecord->Set_Value(0,"T_Rain");
		pRecord->Set_Value(1,T_Rain);
		count++;

		pTable->Add_Record();
		pRecord = pTable->Get_Record(10+count);
		pRecord->Set_Value(0,"T_Melt");
		pRecord->Set_Value(1,T_Melt);
		count++;

		pTable->Add_Record();
		pRecord = pTable->Get_Record(10+count);
		pRecord->Set_Value(0,"DD_Fac");
		pRecord->Set_Value(1,DD_FAC);
		count++;
	}

	pTable->Add_Record();
	pRecord = pTable->Get_Record(10+count);
	pRecord->Set_Value(0,"RR-Delay");
	pRecord->Set_Value(1,delay);
	count++;

	pTable->Add_Record();
	pRecord = pTable->Get_Record(10+count);
	pRecord->Set_Value(0,"RRCoef");
	pRecord->Set_Value(1,RRCoef);
	count++;

	pTable->Add_Record();
	pRecord = pTable->Get_Record(10+count);
	pRecord->Set_Value(0,"NSE");
	pRecord->Set_Value(1,NSE);
	count++;

	pTable->Add_Record();
	pRecord = pTable->Get_Record(10+count);
	pRecord->Set_Value(0,"Area");
	pRecord->Set_Value(1,m_area);
	count++;
}


///////////////////////////////////////////////////////////////////////
//
//		                          DIALOGS
//
///////////////////////////////////////////////////////////////////////

void Cihacres_v1::CreateDialog1()
{
	CSG_Parameter	*pNode;
	CSG_String s;

	pNode = Parameters.Add_Table(
		NULL	, "TABLE"	, _TL("Table"),
		"",
		PARAMETER_INPUT
	);

	Parameters.Add_Table_Field(
		pNode	, "DATE_Field"	, _TL("Date Column"),
		"Select the column containing the Date"
	);

	Parameters.Add_Table_Field(
		pNode	, "DISCHARGE_Field"	, _TL("Streamflow Column"),
		"Select the Column containing Discharge Values"
	);

	Parameters.Add_Table_Field(
		pNode	, "PCP_Field"	, _TL("Precipitation Column"),
		"Select the Column containing precipitation Values"
	);

	Parameters.Add_Table_Field(
		pNode	, "TMP_Field"	, _TL("Temperature Column"),
		"Select the Column containing Temperature Values"
	);

	Parameters.Add_Value(
		pNode,	"USE_TMP",	_TL("Using temperature data?"),
		_TL("If checked, then temperature data are used."),
		PARAMETER_TYPE_Bool, true
	);

	pNode = Parameters.Add_Value(
		NULL,	"AREA",	_TL("Area of the Watershed in [km2]"),
		_TL("Area of the Watershed in [km2] used for unit conversion"),
		PARAMETER_TYPE_Double,
		100.0, 0.00001, true, 0.0, false
	);

	s.Printf("Node2", 2);
		pNode = Parameters.Add_Node(NULL,s,"Non-Linear Module","");

	Parameters.Add_Value(
		pNode,	"CFAC",	_TL("Parameter (c)"),
		_TL("Parameter (c) to fit streamflow volume"),
		PARAMETER_TYPE_Double,
		0.001, 0.0, true, 1.0, true
	);
	Parameters.Add_Value(
		pNode,	"TwFAC",	_TL("(Tw) wetness decline time constant"),
		_TL("Tw is approximately the time constant, or inversely,"
		"the rate at which the catchment wetness declines in the absence of rainfall"),
		PARAMETER_TYPE_Double,
		1.0, 0.01, true, 150.0, true
	);

	s.Printf("Node3", 3);
	pNode = Parameters.Add_Node(NULL,s,"Storage Configuration","");

	Parameters.Add_Choice(
		pNode	, "STORAGE"		, "Storage",
		"",
		CSG_String::Format("%s|%s|%s|",
			_TL("Single Storage"),			//  0
			_TL("Two Parallel Storages"),	//  1 
			_TL("Two Storages in Series !!! not yet implemented !!!")	//  2 
		)
	);

	s.Printf("Node4", 4);
	pNode = Parameters.Add_Node(NULL,s,"IHACRES Version","");

	Parameters.Add_Choice(
		pNode	, "IHACVERS"		, "IHACRES Version",
		"",
		CSG_String::Format("%s|%s|%s|%s|",
			_TL("Jakeman & Hornberger (1993)"),	//  0
			_TL("Kokkonen et al. (2003)"),		//  1 
			_TL("IHACRES v1.0 + SNOW MODULE !!! not yet implemented !!!"),	//  2 
			_TL("Croke et al. (2005) !!! not yet implemented !!!")			//	3

		)
	);

	Parameters.Add_Value(
		pNode,	"SNOW_MODULE",	_TL("Using the snow-melt module?"),
		_TL("If checked, snow-melt module is used."),
		PARAMETER_TYPE_Bool, false
	);

	Parameters.Add_Value(
		NULL,	"WRITEALL_TS",	_TL("Write all calculated Time Series in a table?"),
		_TL("If checked, then a second output table with all Time Series data is created."),
		PARAMETER_TYPE_Bool, true
	);

	Parameters.Add_Table_Output(
		NULL	, "TABLEout"	, _TL("Table"),
		""
	);
	Parameters.Add_Table_Output(
		NULL	, "TABLEparms"	, _TL("Table"),
		""
	);
	Parameters.Add_Table_Output(
		NULL	, "TABLEsettings", _TL("Table"),
		""
	);
}
//---------------------------------------------------------------------
// DIALOG 2
//---------------------------------------------------------------------

void Cihacres_v1::CreateDialog2(bool bTMP, int storconf, int IHAC_version,
								CSG_Table *pTable,
								int dateField, int dischargeField)
{
	CSG_String		s;
	CSG_Parameters	P;  // used to add Parameters in the second dialog
	CSG_Parameter	*pNode, *pNode1;

	//	Dialog design
	P.Set_Name(_TL("Choose Time Range"));

	s.Printf("Node1", 1);
	pNode = P.Add_Node(NULL,s,"Time Range","");

	s.Printf("FDAY" , 1-1);
	P.Add_String(pNode,s,_TL("First Day"),_TL(""),
				 pTable->Get_Record(0)->asString(dateField));

	s.Printf("LDAY" , 1-2);
	P.Add_String(pNode,s,_TL("Last Day"),_TL(""),
				 pTable->Get_Record(pTable->Get_Record_Count()-1)->asString(dateField));


	if (bTMP) // if observed temperature data are used
	{
		s.Printf("Node2", 2);
		pNode = P.Add_Node(NULL,s,"Non-Linear Module","");

		s.Printf("Node2-1", 2-1);
		pNode1 = P.Add_Node(pNode,s,"Temperature Modulation Factor","");

		P.Add_Value(
			pNode1	, "TFac"		, "Temperature Modulation Factor (f)",
			_TL("Temperature Modulation Factor f"),
			PARAMETER_TYPE_Double,
			1.0, 0.0001, true, 10.0, true
		);
	} // End if (bTMP)

	switch(storconf)
	{
	case 0: // single storage
		s.Printf("Node3", 3);
		pNode = P.Add_Node(NULL,s,"Linear Module","");

		s.Printf("Node3-1", 3-1);
		pNode1 = P.Add_Node(pNode,s,"Parameter (a)","");

		P.Add_Value(
			pNode1,	"AFAC",	_TL("(a)"),
			_TL(""),
			PARAMETER_TYPE_Double,
			-0.8, -0.99, true, -0.01, true
		);

		s.Printf("Node3-2", 3-2);
		pNode1 = P.Add_Node(pNode,s,"Parameter (b)","");

		P.Add_Value(
			pNode1,	"BFAC",	_TL("(b)"),
			_TL(""),
			PARAMETER_TYPE_Double,
			0.2, 0.001, true, 1.0, true
		);
		break;

	case 1: // two parallel storages
		s.Printf("Node3", 3);
		pNode = P.Add_Node(NULL,s,"Linear Module","");

		// Parameter a
		s.Printf("Node3-1", 3-1);
		pNode1 = P.Add_Node(pNode,s,"Parameter (a)","");

		P.Add_Value(
			pNode1,	"AQ",	_TL("a(q)"),
			_TL(""),
			PARAMETER_TYPE_Double,
			-0.7, -0.99, true, -0.01, true
		);
		P.Add_Value(
			pNode1,	"AS",	_TL("a(s)"),
			_TL(""),
			PARAMETER_TYPE_Double,
			-0.9, -0.99, true, -0.01, true
		);

		// Parameter b
		s.Printf("Node3-2", 3-2);
		pNode1 = P.Add_Node(pNode,s,"Parameter (b)","");

		P.Add_Value(
			pNode1,	"BQ",	_TL("b(q)"),
			_TL(""),
			PARAMETER_TYPE_Double,
			0.0, 0.0, true, 1.0, true
		);

		//P.Add_Value(
		//	pNode1,	"BS",	_TL("b(s)"),
		//	_TL(""),
		//	PARAMETER_TYPE_Double,
		//	0.0, 0.0, true, 1.0, true
		//);
		break;

	case 2: // two storages in series
		break;
	} // end switch (storconf)

	switch(IHAC_version)
	{
	case 0: break;
	case 1: break;
	case 2:
		s.Printf("Node4", 4);
		pNode = P.Add_Node(NULL,s,"Snow Module","");
		s.Printf("Node4-1", 4-1);
		pNode1 = P.Add_Node(pNode,s,"Snow Parameters","");

		P.Add_Value(
			pNode1,	"T_RAIN",	"Temperature Threshold for Rainfall (lower bound)",
			"Below this threshold precipitation will fall as snow",
			PARAMETER_TYPE_Double,
			-1.0, -10.0, true, 10.0, true
		);
		P.Add_Value(
			pNode1,	"T_MELT",	"Temperature Threshold for Melting (lower bound)",
			"Above this threshold snow will start to melt",
			PARAMETER_TYPE_Double,
			1.0, -5.0, true, 10.0, true
		);
		P.Add_Value(
			pNode1,	"DD_FAC",	"Day-Degree Factor (lower bound)",
			"Day-Degree Factor depends on catchment characteristics",
			PARAMETER_TYPE_Double,
			0.7, 0.7, true, 9.2, true
		);

		break;
	case 3:
		s.Printf("Node4", 4);
		pNode = P.Add_Node(NULL,s,"Soil Moisture Power Eq.","");

		s.Printf("Node4-1", 4-1);
		pNode1 = P.Add_Node(pNode,s,"Parameter l","");

		P.Add_Value(
			pNode1,"L_LB",_TL("l (lower bound)"),
			_TL(""),
			PARAMETER_TYPE_Double,
			0.0, 0.0, true, 5.0, true
		);
		P.Add_Value(
			pNode1,"L_UB",_TL("l (upper bound)"),
			_TL(""),
			PARAMETER_TYPE_Double,
			0.0, 0.0, true, 5.0, true
		);
		
		s.Printf("Node4-2", 4-2);
		pNode1 = P.Add_Node(pNode,s,"Parameter p","");

		P.Add_Value(
			pNode1,"P_LB",_TL("p (lower bound)"),
			_TL(""),
			PARAMETER_TYPE_Double,
			0.0, 0.0, true, 5.0, true
		);
		P.Add_Value(
			pNode1,"P_UB",_TL("p (upper bound)"),
			_TL(""),
			PARAMETER_TYPE_Double,
			0.0, 0.0, true, 5.0, true
		);
		break;
	} // end switch (IHAC_version)

	if (bSnowModule)
	{
	s.Printf("Node5", 5);
	pNode1 = P.Add_Node(NULL,s,"Snow Module Parameters","");
		
		P.Add_Value(
			pNode1,	"T_RAIN",	"Temperature Threshold for Rainfall (lower bound)",
			"Below this threshold precipitation will fall as snow",
			PARAMETER_TYPE_Double,
			-1.0, -10.0, true, 10.0, true
		);
		P.Add_Value(
			pNode1,	"T_MELT",	"Temperature Threshold for Melting (lower bound)",
			"Above this threshold snow will start to melt",
			PARAMETER_TYPE_Double,
			1.0, -5.0, true, 10.0, true
		);
		P.Add_Value(
			pNode1,	"DD_FAC",	"Day-Degree Factor (lower bound)",
			"Day-Degree Factor depends on catchment characteristics",
			PARAMETER_TYPE_Double,
			0.7, 0.7, true, 9.2, true
		);
	}
	s.Printf("Node6", 6);
	pNode1 = P.Add_Node(NULL,s,"Time Delay after Start of Rainfall (INTEGER)","");
		
	P.Add_Value(
		pNode1,	"DELAY",	"Time Delay (Rain-Runoff)",
		"The delay after the start of rainfall, before the discharge starts to rise.",
		PARAMETER_TYPE_Int,
		0, 1, true, 100, true
	);

	// End of second dialog design

	if( SG_UI_Dlg_Parameters(&P, _TL("Choose Time Range")) )
	{
		///////////////////////////////////////////////////////////////
		//
		//                ASSIGN DATA FROM SECOND DIALOG
		//
		///////////////////////////////////////////////////////////////
		date1		= P(CSG_String::Format("FDAY",dateField).c_str())
									->asString();
		date2		= P(CSG_String::Format("LDAY",dischargeField).c_str())
									->asString();
		// if observed temperature data are used
		if (bTMP) f	= P("TFac")		->asDouble();

		if (bSnowModule)
		{
			T_Rain	= P("T_RAIN")		->asDouble();
			T_Melt	= P("T_MELT")		->asDouble();
			DD_FAC	= P("DD_FAC")		->asDouble();
		}
		switch (storconf)
		{
		case 0: // single storage
			a		= P("AFAC")			->asDouble();
			b		= P("BFAC")			->asDouble();
			delay	= P("DELAY")		->asInt();
			break;
		case 1: // two parallel storages
			aq		= P("AQ")			->asDouble();
			as		= P("AS")			->asDouble();
			bq		= P("BQ")			->asDouble();
			//bs		= P("BS")			->asDouble();
			bs = ihacres->Calc_Parm_BS(aq,as,bq);
			delay	= P("DELAY")		->asInt();
			break;
		case 2: // two storages in series
			break;
		} // end switch (storconf)

		switch (IHAC_version)
		{
		case 0: break;
		case 1: break;
		case 2:
			T_Rain	= P("T_RAIN")		->asDouble();
			T_Melt	= P("T_MELT")		->asDouble();
			DD_FAC	= P("DD_FAC")		->asDouble();
			break;
		} // end switch (IHAC_version)
	}
}