///////////////////////////////////////////////////////////
// Author:			Stefan Liersch
// Contact:			stefan.liersch@googlemail.com,
//					stefan.liersch@ufz.de
//
// Date:			2008-09-24
// last modified:	2008-09-24
//
//---------------------------------------------------------
// DESCRIPTION
//---------------------------------------------------------
//
//---------------------------------------------------------
// ToDo
//---------------------------------------------------------
//
///////////////////////////////////////////////////////////


#ifndef HEADER_INCLUDED__SOIL_SALINITY_MAP_H__
#define HEADER_INCLUDED__SOIL_SALINITY_MAP_H__

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

//#include "saga_api/saga_api.h"
#include "saga_api/simplefeature_api.h"

#include "saga_gui/saga_frame.h"		// location of class Cpgdatabase
										// using global *g_pSAGA_Frame pointer
#include "pgsql/pgdatabase.h"

#include <sstream>
#include <string>
#include <vector>
typedef std::vector<int> vector_i;
typedef std::vector<std::string> vector_s;
typedef std::vector<double> vector_d;
//---------------------------------------------------------------------


///////////////////////////////////////////////////////////////////////
//
//	CLASS CParmWeights
//
///////////////////////////////////////////////////////////////////////

class CParmWeights
{
public:
	// These are the default settings for
	// parameter weights.
	// The weights or importance, respectively,
	// were defined during a workshop in Urgensh (Uzbekistan)
	// in the year 2008.
	// The values can range between 1 and 10,
	// where 1 = low importance and 10 = high importance.
	static const int SoilColourLocal	= 5;
	static const int nLeaching			= 10;
	static const int WQ_Leaching		= 10;
	static const int WQ_Irrigation		= 10;
	static const int WVolumeIrrigation	= 5;
	static const int Evenness			= 10;
	static const int Morphology			= 10;
	static const int SoilTexture		= 5;
	static const int PlantGrowth		= 1;
	static const int GWSalinity			= 5;
	static const int GWLevel			= 10;
	static const int nChannels			= 5;
	static const int Distance			= 10;
	static const int Maintenance		= 10;
};
//---------------------------------------------------------------------

///////////////////////////////////////////////////////////////////////
//
//	CLASS CAttributeTableFieldNumbers
//
///////////////////////////////////////////////////////////////////////

class CAttributeTableFieldNumbers
{
public:
	CAttributeTableFieldNumbers(std::string tablename)
	{
		nFields			= 12;
		v_FieldNames.resize(nFields);
		v_FieldNames[0]	= "pk_id";
		v_FieldNames[1]	= "fid";
		v_FieldNames[2]	= "yr";
		v_FieldNames[3]	= "mnth";
		v_FieldNames[4]	= "salinity";
		v_FieldNames[5]	= "salinity_v";
		v_FieldNames[6]	= "salinity_l";
		v_FieldNames[7]	= "salinity_e";
		v_FieldNames[8]	= "ms_low";
		v_FieldNames[9]	= "ms_medium";
		v_FieldNames[10]= "ms_high";
		v_FieldNames[11]= "plant";

		_Set_FieldNumbers(tablename);
	}

	int					Get_nFields()				{ return(nFields);}
	std::string			Get_FieldName(int i)		{ return( i < nFields ? v_FieldNames[i] : "" ); }
	int					Get_FieldNumber_PK_ID()		{ return(pk_id); }
	int					Get_FieldNumber_FID()		{ return(fid); }
	int					Get_FieldNumber_yr()		{ return(yr); }
	int					Get_FieldNumber_mnth()		{ return(mnth); }
	int					Get_FieldNumber_salinity()	{ return(salinity); }
	int					Get_FieldNumber_salinity_v(){ return(salinity_v); }
	int					Get_FieldNumber_salinity_l(){ return(salinity_l); }
	int					Get_FieldNumber_salinity_e(){ return(salinity_e); }
	int					Get_FieldNumber_ms_low()	{ return(ms_low); }
	int					Get_FieldNumber_ms_medium()	{ return(ms_medium); }
	int					Get_FieldNumber_ms_high()	{ return(ms_high); }
	int					Get_FieldNumber_plant()		{ return(plant); }

protected:
	int					pk_id;
	int					fid;
	int					yr;
	int					mnth;
	int					salinity;
	int					salinity_v;
	int					salinity_l;
	int					salinity_e;
	int					ms_low;
	int					ms_medium;
	int					ms_high;
	int					plant;

	int					nFields;
	vector_s			v_FieldNames;

private:
	void _Set_FieldNumbers(std::string tablename)
	{
		std::string			fname;
		std::ostringstream	sql;
		sql << "SELECT * FROM " << tablename << " LIMIT 1";
		
		PGresult* res = g_pSAGA_Frame->db->ExecSQL_wx2(sql.str().c_str());
		if (PQresultStatus(res) != PGRES_TUPLES_OK)
		{
			PQclear(res);
		} else {
			for (int field = 0; field < PQnfields(res); field++) {

				fname = PQfname(res,field);

				if ( fname.compare(v_FieldNames[0]) == 0 ) pk_id		= field;
				if ( fname.compare(v_FieldNames[1]) == 0 ) fid			= field;
				if ( fname.compare(v_FieldNames[2]) == 0 ) yr			= field;
				if ( fname.compare(v_FieldNames[3]) == 0 ) mnth			= field;
				if ( fname.compare(v_FieldNames[4]) == 0 ) salinity		= field;
				if ( fname.compare(v_FieldNames[5]) == 0 ) salinity_v	= field;
				if ( fname.compare(v_FieldNames[6]) == 0 ) salinity_l	= field;
				if ( fname.compare(v_FieldNames[7]) == 0 ) salinity_e	= field;
				if ( fname.compare(v_FieldNames[8]) == 0 ) ms_low		= field;
				if ( fname.compare(v_FieldNames[9]) == 0 ) ms_medium	= field;
				if ( fname.compare(v_FieldNames[10]) == 0 ) ms_high		= field;
				if ( fname.compare(v_FieldNames[11]) == 0 ) plant		= field;
			}
			PQclear(res);
		}
	}
};
//---------------------------------------------------------------------


///////////////////////////////////////////////////////////////////////
//
//	CLASS CSoilSalinityMap
//
///////////////////////////////////////////////////////////////////////

class CSoilSalinityMap
{
public:
	// use this constructor to load a soil salinity map
	CSoilSalinityMap(CSG_SimpleFeature* pSimpleFeature);
	
	// use this constructor to create a soil salinity map
	// on the basis of a shapefile
	CSoilSalinityMap(CSG_Shapes* pShapes);

	~CSoilSalinityMap();
	//---------------------------------------------------------------------

	CSG_SimpleFeature*	Get_SimpleFeature()		{ return(m_pSimpleFeature); }

	CSG_String			Get_MapName()			{ return(m_MapName); }
	CSG_String			Get_AttributeTableName(){ return(m_AttributeTableName); }
	CSG_String			Get_SettingsTableName()	{ return(m_SettingsTableName); }
	CSG_String			Get_WeightsTableName()	{ return(m_WeightsTableName); }

	int					Get_NumberSSVariables()	{ return(m_nSoilSalinityVariables); }

	vector_i			Get_Weights()			{ return(m_v_weights);	}
	int					Get_Weight(int i)		{ return(m_v_weights[i]); }
	bool				Set_Default_Weights();
	bool				Update_Weights(vector_i v_weights);

	CAttributeTableFieldNumbers* Get_AttrFieldName() { return(m_pAttrFieldNumbers); }

private:
	
	CAttributeTableFieldNumbers *m_pAttrFieldNumbers;

	CParmWeights		m_Default_Weights;

	CSG_SimpleFeature*	m_pSimpleFeature;

	CSG_String			m_MapName;
	CSG_String			m_AttributeTableName;
	CSG_String			m_SettingsTableName;
	CSG_String			m_WeightsTableName;

	int					m_nSoilSalinityVariables;
	vector_i			m_v_weights;
	void				_Resize_Weights(int size);
	bool				_Load_Weights();
	bool				_Delete_TableContent_Weights();

	//---------------------------------------------------------------------
	//	CREATE SALINITY MAP (SimpleFeature) FUNCTIONS
	//---------------------------------------------------------------------
	bool				_Export_Shape_As_SoilSalinityMap(CSG_Shapes* pShapes);

	void				_Create_External_Attributes();

	void				_Assign_TableNames(CSG_String m_MapName);

	void				_Add_Specific_Attributes(CSG_Shapes* pShapesOut);

	void				_Add_IDs_To_PK_Field(CSG_Shapes* pShapesOut);

	void				_Create_AttributeTable();

	void				_Create_SettingsTable();

	void				_Create_WeightsTable();

	void				_Insert_DefaultWeights();
	//---------------------------------------------------------------------

};

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

#endif /* HEADER_INCLUDED__SOIL_SALINITY_MAP_H__ */