#include "pgsql/dialogs/pg_dlg_sgtable2pgsql.h"
#include "pgsql/pg_menu_db.h"

#include <fstream>
#include <string>

#define CONFIG_GROUP_FILE_DLG	"/FileDialogs"
#include "saga_gui/helper.h"			// using function MSG_General_Add()
#define MSG_ADD(s)	MSG_General_Add(s, true, true);

///////////////////////////////////////////////////////////
// Author:			Stefan Liersch
// Contact:			stefan.liersch@googlemail.com,
//					stefan.liersch@ufz.de
//
// Date:			2007-07-17
// last modified:	2007-07-18
//
//---------------------------------------------------------
// DESCRIPTION
//---------------------------------------------------------
//	This dialog gets the necessary information to export
//	a SAGA table to a PostgreSQL table.
//---------------------------------------------------------
// ToDo
//---------------------------------------------------------
//	-	IsNumeric_sql() return false if (VARCHAR(x))
//
///////////////////////////////////////////////////////////

//---------------------------------------------------------
BEGIN_EVENT_TABLE(Cdlg_table2pg, wxDialog)
	EVT_CHOICE(ID_CHOICE_TABLE,			_On_ChoiceTableChanged)
	EVT_BUTTON(ID_BUTTON_Load_Settings,	_On_Button_Load_Settings)
	EVT_BUTTON(ID_BUTTON_Save_Settings,	_On_Button_Save_Settings)
END_EVENT_TABLE()

//---------------------------------------------------------
// CONSTRUCTOR
Cdlg_table2pg::Cdlg_table2pg(wxWindow *parent, wxWindowID id, const wxString &title)
							: wxDialog(parent, id, title,
							  wxPoint(100,100), wxDefaultSize,
							  wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)

{
	_CreateDlg();
}
//---------------------------------------------------------
// DESTRUCTOR
Cdlg_table2pg::~Cdlg_table2pg()
{
}
//---------------------------------------------------------

///////////////////////////////////////////////////////////
//
//	DIALOG design
//
///////////////////////////////////////////////////////////

void Cdlg_table2pg::_CreateDlg()
{
    wxBoxSizer *mainBoxSizer = new wxBoxSizer( wxVERTICAL );

	// Box SAGA Table -------------------------------------------------
    wxStaticBox *item3 = new wxStaticBox( this, -1, wxT("SAGA Table") );
	item3->SetFont( wxFont( 8, wxSWISS, wxNORMAL, wxBOLD ) );
    wxStaticBoxSizer *StatBoxTableInfo = new wxStaticBoxSizer( item3, wxVERTICAL );
	wxBoxSizer *hBox1 = new wxBoxSizer(wxHORIZONTAL);
	wxBoxSizer *hBox2 = new wxBoxSizer(wxHORIZONTAL);
	
	wxStaticText *item5 = new wxStaticText( this, ID_TEXT1, wxT("Table:"), wxDefaultPosition, wxSize(90,-1), 0 );
	m_pChoice_Table = new wxChoice(this, ID_CHOICE_TABLE, wxDefaultPosition, wxSize(150,-1), 0, NULL, 0 );
	wxArrayString tables = _GetTableNames();
	for (unsigned int i = 0; i < tables.size(); i++)
		m_pChoice_Table->Append(tables[i]);
	m_pChoice_Table->SetSelection(0);
    hBox1->Add( item5,			0, wxALIGN_LEFT|wxALL, 0 );
	hBox1->Add(m_pChoice_Table,	0, wxALIGN_LEFT|wxLEFT, 10);
	
	wxStaticText *item51 = new wxStaticText( this, ID_TEXT1, wxT("Export Name:"), wxDefaultPosition, wxSize(90,-1), 0 );
	m_pTxtCtrl_ExportName = new wxTextCtrl( this, ID_TxtCtrl_ExportName, wxT(""), wxDefaultPosition, wxSize(150,-1), 0 );
	hBox2->Add(item51,			0,wxALIGN_LEFT|wxALL, 0);
	hBox2->Add(m_pTxtCtrl_ExportName, 0, wxALIGN_LEFT|wxLEFT, 10);

	StatBoxTableInfo->Add(hBox1,0,wxALIGN_LEFT|wxALL,5);
	StatBoxTableInfo->Add(hBox2,0,wxALIGN_LEFT|wxALL,5);
	//-----------------------------------------------------------------

	// wxGrid ---------------------------------------------------------
	wxStaticBox *item195 = new wxStaticBox( this, -1, wxT("PostgreSQL Table Attributes") );
	item195->SetFont( wxFont( 8, wxSWISS, wxNORMAL, wxBOLD ) );
    wxStaticBoxSizer *StatBoxGrid = new wxStaticBoxSizer( item195, wxHORIZONTAL );
    m_pGrid = new wxGrid( this, ID_GRID1, wxDefaultPosition, wxSize(600,300), wxWANTS_CHARS,wxPanelNameStr);
    m_pGrid->CreateGrid( 0, 3, wxGrid::wxGridSelectCells );
	m_pGrid->SetColLabelValue(0,"Name");
	m_pGrid->SetColLabelValue(1,"SQL Field Type");
	m_pGrid->SetColLabelValue(2,"Constraint");
	m_pGrid->SetColSize(0,150);
	m_pGrid->SetColSize(1,120);
	m_pGrid->SetColSize(2,210);
	StatBoxGrid->Add(m_pGrid, 1, wxGROW|wxALL, 0);
	//-----------------------------------------------------------------

	// Button Box Settings ----------------------------------------------
	wxBoxSizer *ButtonBox_Settings = new wxBoxSizer( wxHORIZONTAL );
	m_pButLoad = new wxButton( this, ID_BUTTON_Load_Settings, wxT("Load Settings"), wxDefaultPosition, wxDefaultSize, 0 );
	m_pButSave = new wxButton( this, ID_BUTTON_Save_Settings, wxT("Save Settings"), wxDefaultPosition, wxDefaultSize, 0 );

    ButtonBox_Settings->Add( m_pButLoad, 0, wxALIGN_CENTER|wxALL, 5 );
	ButtonBox_Settings->Add( m_pButSave, 0, wxALIGN_CENTER|wxALL, 5 );
	m_pButLoad->Disable();
	m_pButSave->Disable();
	//-----------------------------------------------------------------

	// Button Box Export ----------------------------------------------
	wxBoxSizer *ButtonBox = new wxBoxSizer( wxHORIZONTAL );
    m_pButExport = new wxButton( this, wxID_OK, wxT("Export"), wxDefaultPosition, wxDefaultSize, 0 );
	wxButton *ButCancel = new wxButton( this, wxID_CANCEL, wxT("Cancel"), wxDefaultPosition, wxDefaultSize, 0 );

    ButtonBox->Add( m_pButExport, 0, wxALIGN_CENTER|wxALL, 5 );
	ButtonBox->Add( ButCancel, 0, wxALIGN_CENTER|wxALL, 5 );
	m_pButExport->Disable();
	//-----------------------------------------------------------------

	mainBoxSizer->Add(StatBoxTableInfo,0,wxALIGN_LEFT|wxALL,5);
	mainBoxSizer->Add(StatBoxGrid,1,wxGROW|wxALL,5);
	mainBoxSizer->Add(ButtonBox_Settings,0,wxALIGN_CENTER|wxALL,5);
	mainBoxSizer->Add(ButtonBox,0,wxALIGN_CENTER|wxALL,5);
	//-----------------------------------------------------------------

    this->SetSizer( mainBoxSizer );
	mainBoxSizer->Fit(this);
    mainBoxSizer->SetSizeHints( this );
}
//---------------------------------------------------------

wxArrayString Cdlg_table2pg::_GetTableNames()
{
	wxArrayString TableNames;
	if (_SetTableManager())
	{
		for (int i = 0; i < m_pTableManager->Get_Count(); i++)
		{
			TableNames.Add(m_pTableManager->Get_Table(i)->Get_Name());
		}
	}
	return(TableNames);
}
//---------------------------------------------------------

bool Cdlg_table2pg::_SetTableManager()
{
	// assign 'm_pTableManager'
	if ( (m_pTableManager = g_pData->Get_Tables()) != NULL)
	{
		return(true);
	} else {
		return(false);
	}
}

///////////////////////////////////////////////////////////
//
//	On_Choice_Changed Functions
//
///////////////////////////////////////////////////////////

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

void Cdlg_table2pg::_On_ChoiceTableChanged(wxCommandEvent &event)
{
	m_pButExport->Enable();
	m_pButLoad->Enable();
	m_pButSave->Enable();
	if (_SetExportName())
	{
		m_pExportTable = _GetExportTable();

		_Set_GRID_FieldNames();
	
		// set correlating sql field type
		m_pIsNumeric = new bool[m_pExportTable->Get_Field_Count()];
		_Set_GRID_FieldTypes();

		_Set_GRID_Constraints();
	}
	event.Skip();
}
//---------------------------------------------------------

void Cdlg_table2pg::_On_Button_Load_Settings(wxCommandEvent &event)
{
	wxString def_Dir;
	CONFIG_Read(CONFIG_GROUP_FILE_DLG, "TAB_LOAD", def_Dir);

	wxString wildcard =	wxT("Export Settings (*.exps)|*.exps");
	wxFileDialog dialog(this, wxT("Choose a file"), 
						//::wxGetCwd(),wxT(""),	wildcard, wxOPEN);
						def_Dir, wxT(""),wildcard, wxOPEN);
	if (dialog.ShowModal() == wxID_OK)
	{
		wxString path = dialog.GetPath();
		//int filterIndex = dialog.GetFilterIndex();	

		std::string line;
		std::ifstream InFile(path);

		if (InFile.is_open())
		{
			for (int col = 0; col < m_pGrid->GetNumberCols(); col++)
			{
				for (int row = 0; row < m_pGrid->GetNumberRows(); row++)
				{
					getline(InFile, line);
					m_pGrid->SetCellValue(row,col,line.c_str());
				}
			}
			InFile.close();
		}
	}
}
//---------------------------------------------------------

void Cdlg_table2pg::_On_Button_Save_Settings(wxCommandEvent &event)
{
	wxString def_Dir;
	CONFIG_Read(CONFIG_GROUP_FILE_DLG, "TAB_LOAD", def_Dir);

	wxString wildcard =	wxT("Export Settings (*.exps)|*.exps");
	wxFileDialog dialog(this, wxT("Choose a file"), 
						//::wxGetCwd(),wxT(""),	wildcard, wxSAVE);
						def_Dir,wxT(""),	wildcard, wxSAVE);
	if (dialog.ShowModal() == wxID_OK)
	{
		wxString path = dialog.GetPath();
		//int filterIndex = dialog.GetFilterIndex();

		std::ofstream file(path);
		for (int col = 0; col < m_pGrid->GetNumberCols(); col++)
		{
			for (int row = 0; row < m_pGrid->GetNumberRows(); row++)
			{
				file << m_pGrid->GetCellValue(row,col) << std::endl;
			}
		}
		file.close();
	}
}
//---------------------------------------------------------

bool Cdlg_table2pg::_SetExportName()
{
	Cmenu_db menu_db;
	if (m_pChoice_Table->GetString(m_pChoice_Table->GetSelection()) != "")
	{
		m_pTxtCtrl_ExportName->SetValue(menu_db._Reduce_TableName(m_pChoice_Table->GetString(m_pChoice_Table->GetSelection()), '.'));
		return(true);
	} else {
		return(false);
	}
}
//---------------------------------------------------------

CSG_Table* Cdlg_table2pg::_GetExportTable()
{
	return( m_pTableManager->Get_Table(m_pChoice_Table->GetSelection())->Get_Table() );
}
//---------------------------------------------------------

void Cdlg_table2pg::_Set_GRID_FieldNames()
{
	if (m_pGrid->GetNumberRows() > 0)
		m_pGrid->DeleteRows(0, m_pGrid->GetNumberRows(), true);

	m_pGrid->AppendRows(m_pExportTable->Get_Field_Count());
	for (int i = 0; i < m_pExportTable->Get_Field_Count(); i++)
	{
		m_pGrid->SetCellValue(i,0,m_pExportTable->Get_Field_Name(i));
	}
}
//---------------------------------------------------------

void Cdlg_table2pg::_Set_GRID_FieldTypes()
{
	int column = 1; // SQL Field Type column
	int row = 0;
	for (int col = 0; col < m_pExportTable->Get_Field_Count(); col++)
	{
		row = col;
		m_pGrid->SetCellEditor(row, column, new wxGridCellChoiceEditor(WXSIZEOF(m_SQL_FTypes), m_SQL_FTypes));
		m_pGrid->SetCellSize(row, column, 1, 1);
		_Set_GRID_FieldType(row); //m_pGrid->SetCellValue(0, 1, m_SQL_FTypes[0]);
		m_pGrid->SetCellOverflow(row, column, false);
	}
}

//---------------------------------------------------------------------
void Cdlg_table2pg::_Set_GRID_FieldType(int row)
{
	ESG_Table_FieldType FType;
	FType			= (m_pExportTable->Get_Field_Type(row));
	switch (FType)
	{
		case TABLE_FIELDTYPE_Char :
			for (unsigned int j = 0; j < WXSIZEOF(m_SQL_FTypes); j++)
			{
				if (m_SQL_FTypes[j] == "CHAR")
				{
					m_pGrid->SetCellValue(row,1,m_SQL_FTypes[j]);
					m_pIsNumeric[row] = false;
				}
			}
			break;
		case TABLE_FIELDTYPE_String :
			for (unsigned int j = 0; j < WXSIZEOF(m_SQL_FTypes); j++)
			{
				if (m_SQL_FTypes[j] == "VARCHAR")
				{
					m_pGrid->SetCellValue(row,1,m_SQL_FTypes[j]);
					m_pIsNumeric[row] = false;
				}
			}
			break;
		case TABLE_FIELDTYPE_Short :
			for (unsigned int j = 0; j < WXSIZEOF(m_SQL_FTypes); j++)
			{
				if (m_SQL_FTypes[j] == "INT4")
				{
					m_pGrid->SetCellValue(row,1,m_SQL_FTypes[j]);
					m_pIsNumeric[row] = true;
				}
			}
			break;
		case TABLE_FIELDTYPE_Int :
			for (unsigned int j = 0; j < WXSIZEOF(m_SQL_FTypes); j++)
			{
				if (m_SQL_FTypes[j] == "INT8")
				{
					m_pGrid->SetCellValue(row,1,m_SQL_FTypes[j]);
					m_pIsNumeric[row] = true;
				}
			}
			break;
		case TABLE_FIELDTYPE_Long :
			for (unsigned int j = 0; j < WXSIZEOF(m_SQL_FTypes); j++)
			{
				if (m_SQL_FTypes[j] == "INT8")
				{
					m_pGrid->SetCellValue(row,1,m_SQL_FTypes[j]);
					m_pIsNumeric[row] = true;
				}
			}
			break;
		case TABLE_FIELDTYPE_Float :
			for (unsigned int j = 0; j < WXSIZEOF(m_SQL_FTypes); j++)
			{
				if (m_SQL_FTypes[j] == "FLOAT4")
				{
					m_pGrid->SetCellValue(row,1,m_SQL_FTypes[j]);
					m_pIsNumeric[row] = true;
				}
			}
			break;
		case TABLE_FIELDTYPE_Double :
			for (unsigned int j = 0; j < WXSIZEOF(m_SQL_FTypes); j++)
			{
				if (m_SQL_FTypes[j] == "FLOAT8")
				{
					m_pGrid->SetCellValue(row,1,m_SQL_FTypes[j]);
					m_pIsNumeric[row] = true;
				}
			}
			break;
		default:
			for (unsigned int j = 0; j < WXSIZEOF(m_SQL_FTypes); j++)
			{
				if (m_SQL_FTypes[j] == "VARCHAR")
				{
					m_pGrid->SetCellValue(row,1,m_SQL_FTypes[j]);
					m_pIsNumeric[row] = false;
				}
			}
	} // end switch
}

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

void Cdlg_table2pg::_Set_GRID_Constraints()
{
	int column = 2; // SQL Constraint column
	int row = 0;
	for (int col = 0; col < m_pExportTable->Get_Field_Count(); col++)
	{
		row = col;
		m_pGrid->SetCellEditor(row, column, new wxGridCellChoiceEditor(WXSIZEOF(m_Constraints), // count
																	   m_Constraints,			// array of strings
																	   true));					// allow user to add string
		m_pGrid->SetCellSize(row, column, 1, 1);
		m_pGrid->SetCellValue(row,column,m_Constraints[0]);
		m_pGrid->SetCellOverflow(row, column, false);
	}
}
//---------------------------------------------------------


///////////////////////////////////////////////////////////
//
//	Public GET-Functions
//
///////////////////////////////////////////////////////////

const char* Cdlg_table2pg::Get_ExportTableName()
{
	m_pTxtCtrl_ExportName->SelectAll();
	return((const char*)m_pTxtCtrl_ExportName->GetStringSelection().c_str());
}
wxString Cdlg_table2pg::Get_ExportTableName_wxString()
{
	m_pTxtCtrl_ExportName->SelectAll();
	return(m_pTxtCtrl_ExportName->GetStringSelection());
}
//---------------------------------------------------------
const char* Cdlg_table2pg::Get_FieldName(int i)
{
	int col = 0; // Field name column
	if (i < m_pExportTable->Get_Field_Count())
		return(m_pGrid->GetCellValue(i,col).c_str());
	else
		return("Column does not exist");
}

wxString Cdlg_table2pg::Get_FieldName_wxString(int i)
{
	int col = 0; // Field name column
	if (i < m_pExportTable->Get_Field_Count())
		return(m_pGrid->GetCellValue(i,col));
	else
		return("Column does not exist");
}
//---------------------------------------------------------

const char* Cdlg_table2pg::Get_FieldType(int i)
{
	int col = 1; // Field type column
	if (i < m_pExportTable->Get_Field_Count())
		return(m_pGrid->GetCellValue(i,col).c_str());
	else
		return("Column does not exist");
}
//---------------------------------------------------------

const char* Cdlg_table2pg::Get_Constraint(int i)
{
	int col = 2; // Constraint column
	if (i < m_pExportTable->Get_Field_Count())
		return(m_pGrid->GetCellValue(i,col).c_str());
	else
		return("Column does not exist");
}
//---------------------------------------------------------

bool Cdlg_table2pg::IsNumeric(int i)
{
	if (i < m_pExportTable->Get_Field_Count())
		return(m_pIsNumeric[i]);
	else return(false);
}
//---------------------------------------------------------
bool Cdlg_table2pg::IsNumeric_sql(int col)
{
	// Note: Columns and rows are transformed in the dialog grid that shows the
	// export table definitions!
	// Thats why GetCellValue() has col instead of row in the first place.
	if (col < m_pExportTable->Get_Field_Count())
	{
		if(m_pGrid->GetCellValue(col,1).c_str() == "BOOL")
			return(false);
		if(m_pGrid->GetCellValue(col,1).c_str() == "CSTRING")
			return(false);
		if(m_pGrid->GetCellValue(col,1).c_str() == "DATE")
			return(false);
		if(m_pGrid->GetCellValue(col,1).c_str() == "TEXT")
			return(false);
		if(m_pGrid->GetCellValue(col,1).c_str() == "TIME")
			return(false);
		if(m_pGrid->GetCellValue(col,1).c_str() == "TINTERVAL")
			return(false);
		if(m_pGrid->GetCellValue(col,1).c_str() == "UNKNOWN")
			return(false);
		if(m_pGrid->GetCellValue(col,1).c_str() == "VARCHAR")
			return(false);
		if(m_pGrid->GetCellValue(col,1).c_str() == "CHAR")
			return(false);
	}
	return(false);
}
//---------------------------------------------------------
