////////////////////////////////////////////////////////////////
// Implementation of the OGC SimpleFeature in SAGA-GIS
//
// Author:
// Stefan Liersch: stliersch@freenet.de, stefan.liersch@ufz.de
// 2006-11-01
////////////////////////////////////////////////////////////////

#ifndef HEADER_INCLUDED__SimpleFeature_H
#define HEADER_INCLUDED__SimpleFeature_H

#include <vector>
#include <string>

using std::vector;
using std::string;

#include "libpq-fe.h"

#include "sqltable.h"
#include "pgdatabase.h" // in order to access GetFieldTypeString()
//-----------------------------------------------
// a geometry point of the simple feature
// consisting of two coordinates (x and y)
struct SF_TPoint
{
	double x, y;
};
typedef vector< vector<SF_TPoint> > vector_SF_TPoint;
//-----------------------------------------------
// the geometry type of the simple feature
enum SF_TGeometry
{
	SF_point					= 1,
	SF_linestring,
	SF_polygon,
	SF_MultiPoint,
	SF_MultiLinestring,
	SF_MultiPolygon,
	SF_GeometryCollection
};
//-----------------------------------------------
typedef vector<int> vector_int;
//-----------------------------------------------

class CSimpleFeature : public Csqltable
{
public:
	// as WKT (Well-known Text Representation for Geometry)
	CSimpleFeature(PGconn *conn, const char *tablename);

	CSimpleFeature(class Cpgdatabase *pgdb, PGconn *conn, const char *tablename);

	~CSimpleFeature(void);


	/////////////////////////////////////////////
	//				GET FUNCTIONS
	/////////////////////////////////////////////
	string				GetFeatureName();
	string				GetTableCatalog();
	string				GetTableSchema();
	string				GetGeometryColumnName();
	int					GetGeometryColumnNumber();
	int					GetCoordDimension();
	int					GetSRID();
	string				GetSRID_asString();
	string				GetGeoType_asString();
	int					GetGeoType();
	string				GetNN();
	//-------------------------------------------
	int					GetSRID_PK();
	string				GetAuth_Name();
	int					GetAuth_SRID();
	string				GetsrText();
	string				Getproj4text();
	//-------------------------------------------
	unsigned int		GetNumFeatures();
	unsigned int		GetTotalNumPoints();
	unsigned int		GetNumPointsFeature(unsigned int nFeature);
	//vector_SF_TPoint	GetPoint(unsigned int nFeature, unsigned int PointID);
	double				Get_X_Value(unsigned int nFeature, unsigned int PointID);
	double				Get_Y_Value(unsigned int nFeature, unsigned int PointID);
	string				GetWKT(); // GEOMETRY_COLUMN entry in Well-Known-Text
	//-------------------------------------------

	int					GetETYPE();

private:
	PGconn				*conn;
	PGresult			*res;

	string				spatialstr; // Spatial Column as WKT


	/////////////////////////////////////////////
	//			Simple Features Attributes
	/////////////////////////////////////////////
	//-------------------------------------------
	// Table GEOMETRY_COLUMNS
	//-------------------------------------------
	string				FeatureName;
	string				NN; // returns the first field (res,0,0)
	string				TableCatalog;
	string				TableSchema;
	string				GeometryColumnName;
	int					GeometryColumnNumber;
	int					CoordDimension;
	int					SRID;
	string				SRID_asString;
	string				GeoType_asString;
	SF_TGeometry		GeoType;			// Geometry Type as SF_TGeometry	
	//-------------------------------------------
	// Table SPATIAL_REF_SYS
	//-------------------------------------------
	int					SRID_PK;
	string				Auth_Name;
	int					Auth_SRID;
	string				srText;
	string				proj4text;
	//-------------------------------------------
	// Geometry Table
	//-------------------------------------------
	// number of Features in SimpleFeature
	// e.g. number of linestrings in MULTILINESTRING
	unsigned int		nFeatures;
	vector_int			nPoints_Feature;	// number of points per feature
	unsigned int		nPoints;			// total number of points in SimpleFeature
	vector_SF_TPoint	SF_Point;			// SimpleFeature Point
	
	// element tpye of this primitive element for the geometric object
	int					ETYPE;				// 1 = Point, 2 = LineString, 3 = Polygon	
	int					FID;				// Feature identifier

	//STORAGE_TYPE: the type of storage being used for this geometry column
	// 0 = normalized (WKT), 1 = binary (WKB)
	int					storage_type;		// not yet implemented
	// identity of this geometric object
	// the GID should correspond to the number of feature
	// first GID always = 0 or 1
	int					GID;				// not yet implemented
	// identifies multiple components within a geometric object
	int					ESEQ;				// not yet implemented

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

	bool				Initialize(const char *tablename);

	SF_TGeometry		AssignGeoType(const string &s);
	int					AssignETYPE(SF_TGeometry gt);

	void				Resize_SF_TPoint(int nFeatures, vector_int nPoints_Feature);

	void				SelectAssignMethod(SF_TGeometry Geometry);

	// Assigns coordinates to SF_Point.x and SF_Point.y
	// Single-features
	void				AssignCoordinatesPoint(string &str_in);
	void				AssignCoordinatesLinestring(string &str_in);
	void				AssignCoordinatesMultiPoint(string &str_in);
	void				AssignCoordinatesPolygon(string &str_in);
	// Multi-features
	void				AssignCoordinatesMultiLinestring(string &str_in);
	void				AssignCoordinatesMultiPolygon(string &str_in);
	// Assigns coordinates to SF_Point.x and SF_Point.y
	void				AssignCoordinatesSingleFeature(string &str_in);
	void				AssignCoordinatesMultiFeature(string &str_in, int nFeatures);

	vector_int			Assign_nPointsToFeature(string &str_in, int nFeatures);


	unsigned int		FindFirstCharPosition(string &s,	char search_char);

	// Counts the number of search_char in str_in
	unsigned int		CountCharInString(string &str_in, char search_char);

	// if character 'c' is a number function returns true
	bool				IsNumber(char c);


	class Cpgdatabase	*pgdb;

}; // end class CSimpleFeature

#endif /* #ifndef HEADER_INCLUDED__SimpleFeature */