#include "PGSQL/menu_db.h"
// SAGA Header
#include "saga_gui/saga_frame.h"		// location of class Cpgdatabase
										// using global *g_pSAGA_Frame pointer
#include "saga_gui/wksp_data_manager.h" // adding items to SAGA Workspace *g_pData
#include "saga_gui/helper.h"			// using function MSG_General_Add()
#include "saga_gui/res_dialogs.h"		// using DLG_Parameters
#include "saga_gui/res_commands.h"		// Definitions of menu constants (event handler)

#define MSG_ADD(s)	MSG_General_Add(s, true, true);

// ------------------------------------------------------------------------
void Cmenu_db::_On_ConnectDB(void)
{
	try
	{
		// db object must be destroyed (but when and where)??????
		g_pSAGA_Frame->db = new Cpgdatabase();

		// make a connection to the database
		if (g_pSAGA_Frame->db->ConnectToDB(host.c_str(),port.c_str(),
							options.c_str(),tty.c_str(),
							dbname.c_str(),user.c_str(),password.c_str()))
		{
			g_pSAGA_Frame->DB_CONNECTED = true;
			MSG_ADD(wxString::Format("%s%s%s","Database ", dbname.c_str(), " connected"));
			// enable / disable Menu items due to connection status
			m_pDB_Menu->Enable(ID_CMD_MENU_DB_CONN, false);
			m_pDB_Menu->Enable(ID_CMD_MENU_DB_DECONN, true);
			m_pDB_Menu->Enable(MENU_DB_TABLE, true);
			m_pDB_Menu->Enable(MENU_DB_VECTOR, true);
		} else {
			g_pSAGA_Frame->DB_CONNECTED = false;
			MSG_ADD(wxString::Format("%s%s%s","Database ", dbname.c_str(), " not connected"));
			// enable / disable Menu items due to connection status
			m_pDB_Menu->Enable(ID_CMD_MENU_DB_CONN, true);
			m_pDB_Menu->Enable(ID_CMD_MENU_DB_CONN, false);
			m_pDB_Menu->Enable(MENU_DB_TABLE, false);
			m_pDB_Menu->Enable(MENU_DB_VECTOR, true);
			g_pSAGA_Frame->db->ExitDB();
		}
	}
	catch(...)
	{
		MSG_ADD("Connecting Database not successfull!");
	}
}
// ------------------------------------------------------------------------

void Cmenu_db::_On_DeConnectDB()
{
	g_pSAGA_Frame->db->ExitDB();
	MSG_ADD(wxString::Format("%s%s%s","Database ", dbname.c_str(), " disconnected"));
	g_pSAGA_Frame->DB_CONNECTED = false;
	
	// enable / disable Menu items due to connection status
	m_pDB_Menu->Enable(ID_CMD_MENU_DB_CONN, true);
	m_pDB_Menu->Enable(ID_CMD_MENU_DB_DECONN, false);
	m_pDB_Menu->Enable(MENU_DB_TABLE, false);
	m_pDB_Menu->Enable(MENU_DB_VECTOR, false);
}
// ------------------------------------------------------------------------

void Cmenu_db::_On_DB_ImportTable()
{
	CSG_Table		*pTable;
	//-----------------------------------------------------
	// DIALOG
	//-----------------------------------------------------
	string			tablename;
	CSG_Parameters	P;

	P.Set_Name(LNG("Import Table from Database"));

	P.Add_Choice(
		NULL	, "TABLE"	, LNG("Select Import Table"),
		"",
		g_pSAGA_Frame->db->GetDBTables().c_str()
	);

	//-----------------------------------------------------
	if( DLG_Parameters(&P) )
	{
		try
		{
			tablename	= P("TABLE")->asString();

			m_psqltable = new Csqltable(tablename,
										g_pSAGA_Frame->db->GetNumberCols(tablename.c_str()),
										g_pSAGA_Frame->db->GetNumberRows(tablename.c_str()));

			if (g_pSAGA_Frame->db->ReadTable(m_psqltable))
			{
				MSG_ADD("Read Table successfull");
				//-----------------------------------------------------
				// create SAGA Table from database table
				pTable = SG_Create_Table();
				CreateSAGATable(m_psqltable, pTable);
				
				// add table to SAGA Workspace
				pTable->Set_Name(tablename.c_str());
				g_pData->Add(pTable);

				delete m_psqltable;

			} else {
				MSG_ADD("Read Table not successfull");
			}

		}
		catch(...)
		{
			MSG_ADD("Read Table not successfull");
		}

	} // end if (DLG_Parameters(...))
}
// ------------------------------------------------------------------------

void Cmenu_db::_On_DB_ExportTable()
{
	CSG_Table			*pTable;
	Csqltable			*SQLTable;
	ESG_Table_FieldType	FType; // SAGA_API/table.h
	//string				record;
	char				record[4096];
	char				del[4096] = "";
	CSG_String			val;
	int					i;
	
	// select table to export from SAGA workspace
	try
	{
		pTable = SelectSAGATable();
	}
	catch(...)
	{
	}
	if (pTable == NULL)
	{
		MSG_ADD("Select table failed");
	} else {
		MSG_ADD(pTable->Get_Name());
		// prepare SQLTable Fields to be created
		SQLTable = new Csqltable(pTable->Get_Name(),
								pTable->Get_Field_Count(),
								pTable->Get_Record_Count());

		// define sqltable field names and types
		for (i = 0; i < pTable->Get_Field_Count(); i++)
		{
			SQLTable->SetFieldName(pTable->Get_Field_Name(i),i);// = (pTable->Get_Field_Name(i));
			FType			= (pTable->Get_Field_Type(i));
			switch (FType)
			{
				case TABLE_FIELDTYPE_Char :
					SQLTable->SetFieldType("CHAR",i);
					break;
				case TABLE_FIELDTYPE_String :
					SQLTable->SetFieldType("VARCHAR",i);
					break;
				case TABLE_FIELDTYPE_Short :
					SQLTable->SetFieldType("INT4",i);
					break;
				case TABLE_FIELDTYPE_Int :
					SQLTable->SetFieldType("INT8",i);
					break;
				case TABLE_FIELDTYPE_Long :
					SQLTable->SetFieldType("INT8",i);
					break;
				case TABLE_FIELDTYPE_Float :
					SQLTable->SetFieldType("FLOAT4",i);
					break;
				case TABLE_FIELDTYPE_Double :
					SQLTable->SetFieldType("FLOAT8",i);
					break;
				default : SQLTable->SetFieldType("VARCHAR",i);
			} // end switch
		}

		// create table fields in current PostgreSQL database
		if (g_pSAGA_Frame->db->CreateTable(SQLTable))
		{
			MSG_ADD("Create Table successfull");
		} else {
			MSG_ADD("Create Table not successfull");
		}

		// create records / insert values into table matrix
		for (int y = 0; y < pTable->Get_Record_Count(); y++)
		{
			strcpy(record,del); // delete variable record
			for (int x = 0; x < pTable->Get_Field_Count(); x++)
			{
				FType = (pTable->Get_Field_Type(x));
				switch (FType)
				{
					case TABLE_FIELDTYPE_Char :
						strcat(record,"'");
						strcat(record,pTable->Get_Record(y)->asString(x));
						strcat(record,"'");
						if (x + 1 < pTable->Get_Field_Count()) strcat(record, ",");
						break;
					case TABLE_FIELDTYPE_String :
						strcat(record,"'");
						strcat(record,pTable->Get_Record(y)->asString(x));
						strcat(record,"'");
						if (x + 1 < pTable->Get_Field_Count()) strcat(record, ",");
						break;
					case TABLE_FIELDTYPE_Short :
						strcat(record,pTable->Get_Record(y)->asString(x));
						if (x + 1 < pTable->Get_Field_Count()) strcat(record, ",");
						break;
					case TABLE_FIELDTYPE_Int :
						strcat(record,pTable->Get_Record(y)->asString(x));
						if (x + 1 < pTable->Get_Field_Count()) strcat(record, ",");
						break;
					case TABLE_FIELDTYPE_Long :
						strcat(record,pTable->Get_Record(y)->asString(x));
						if (x + 1 < pTable->Get_Field_Count()) strcat(record, ",");
						break;
					case TABLE_FIELDTYPE_Float :
						strcat(record,pTable->Get_Record(y)->asString(x));
						if (x + 1 < pTable->Get_Field_Count()) strcat(record, ",");
						break;
					case TABLE_FIELDTYPE_Double :
						strcat(record,pTable->Get_Record(y)->asString(x));
						if (x + 1 < pTable->Get_Field_Count()) strcat(record, ",");
						break;
					default:
						strcat(record,"'");
						strcat(record,pTable->Get_Record(y)->asString(x));
						strcat(record,"'");
						if (x + 1 < pTable->Get_Field_Count()) strcat(record, ",");
						break;
				} // end switch

			} // end if (int x...

			// insert values into table
			g_pSAGA_Frame->db->InsertIntoTable(SQLTable->GetTableName().c_str(), record);
		} // end if (int y...
	}
}
// ------------------------------------------------------------------------

void Cmenu_db::_On_DB_DeleteTable()
{
	string			tablename;
	CSG_Parameters	P;

	P.Set_Name(LNG("Delete Table from Database"));

	P.Add_Choice(
		NULL	, "TABLE"	, LNG("Select Import Table"),
		"",
		g_pSAGA_Frame->db->GetDBTables().c_str()
	);

	//-----------------------------------------------------
	if( DLG_Parameters(&P) )
	{
		tablename	= P("TABLE")->asString();

		if (g_pSAGA_Frame->db->DropTable(tablename.c_str()))
		{
			MSG_ADD("Table deleted");
		}
		else {
			MSG_ADD("Failed to delete table");
		}
	}
}
// ------------------------------------------------------------------------

string Cmenu_db::Get_FieldTypeFromSAGA(TSG_Table_Field_Type SG_ft)
{
	switch(SG_ft)
	{
	case TABLE_FIELDTYPE_None :
		return("UNKNOWN"); break;
	case TABLE_FIELDTYPE_Char :
		return("VARCHAR(1)"); break;
	case TABLE_FIELDTYPE_Short :
		return("INT4"); break;
	case TABLE_FIELDTYPE_Int :
		return("INT8"); break;
	case TABLE_FIELDTYPE_Long :
		return("INT8"); break;
	case TABLE_FIELDTYPE_Float :
		return("FLOAT4"); break;
	case TABLE_FIELDTYPE_Double :
		return("FLOAT8"); break;
	case TABLE_FIELDTYPE_String :
		return("VARCHAR"); break;
	case TABLE_FIELDTYPE_Color :
		return("UNKNOWN"); break;

	default: return("UNKNOWN");
	}
}
// ------------------------------------------------------------------------

bool Cmenu_db::is_numeric(TSG_Table_Field_Type SG_FT)
{
	switch (SG_FT)
	{
	case TABLE_FIELDTYPE_None :
		return(false); break;
	case TABLE_FIELDTYPE_Char :
		return(false); break;
	case TABLE_FIELDTYPE_Short :
		return(true); break;
	case TABLE_FIELDTYPE_Int :
		return(true); break;
	case TABLE_FIELDTYPE_Long :
		return(true); break;
	case TABLE_FIELDTYPE_Float :
		return(true); break;
	case TABLE_FIELDTYPE_Double :
		return(true); break;
	case TABLE_FIELDTYPE_String :
		return(false); break;
	case TABLE_FIELDTYPE_Color :
		return(false); break;

	default: return(false); 
	} // end switch
}