#include "database.h"

using namespace Database;

wxDbConnectInf *Database::dbConnectInf;
wxDb *Database::db;

bool Database::SetupConnection()
{
	wxConfigBase *pConfig = wxConfigBase::Get();

	pConfig->SetPath(_T("/Database"));
	// DSN settings set, try making connection
	wxString dsn = pConfig->Read(_T("DSN"), "NestDSN");
	wxString user = pConfig->Read(_T("Username"),"nest");
	wxString pass = pConfig->Read(_T("Password"),"5au5age5");

	// make connection
	Database::dbConnectInf = new wxDbConnectInf(NULL, dsn, user, pass);
	if (Database::dbConnectInf)
		return true;
	return false;
}
bool Database::SelectInt(int &value, wxString sqlStmt)
{
	SDWORD cb;
	ULONG reqQty;

	// Perform the query
	if (!Database::db->ExecSql(sqlStmt.c_str()))
	{
		wxLogError("Unable to execute SQL statement.");
		return false;
	}

	// Request the first row of the result set
	if (!Database::db->GetNext())
	{
		// ERROR
		wxLogError("Unable to retrieve result.");
		return false;
	}

	// Read column #1 of the row returned by the call to ::GetNext()
	// and return the value in 'reqQty'
	if (!Database::db->GetData(1, SQL_C_ULONG, &reqQty, 0, &cb))
	{
		// ERROR
		wxLogError("Unable to retrieve data.");
		return false;
	}

	// Check for a NULL result
	if (cb != SQL_NULL_DATA)
	{
		value = reqQty;
		return true;
	}
	return false;
}
bool Database::SetupDatabase()
{
	if (!Database::dbConnectInf)
		SetupConnection();

	db = wxDbGetConnection(Database::dbConnectInf);

	if (!db)
	{
		wxLogError(_T("Failed to open connection to datasource"));
		return false;
	}
	// test if table USERS exists
	if (!db->TableExists(_T("USERS")))
	{

		wxDb *db = wxDbGetConnection(dbConnectInf);
		if (db==0)
		{
			wxLogError(_T("Connection to DB failed!"));
			return FALSE;
		}
		bool success = false;
		// connection established, build table for user info
		UserTable *table = new UserTable(db);
		if (table==0)
		{
			// failed to instantiate table
			wxLogError(_T("Creation of UserTable object failed!"));
			return false;
		}
		table->GetDb()->RollbackTrans();
		if (!table->CreateTable(FALSE))
		{
			wxLogError(wxT("Error creating USERS table."));
		}
		else
		{
			wxLogMessage(wxT("USERS table succesfully created"));
			success = true;
		}

		if (table)
		{
			wxDELETE(table)
			table = NULL;
		}

		wxDbFreeConnection(db);
		return success;
	}
	return true;
}

UserTable::UserTable (wxDb *pwxDb) : wxDbTable(pwxDb ? pwxDb : wxDbGetConnection(dbConnectInf),
											   "USERS", 14, wxT(""),
											   !wxDB_QUERY_ONLY, dbConnectInf->GetDefaultDir())
{
	// This is used to represent whether the database connection should be released
	// when this instance of the object is deleted.  If using the same connection
	// for multiple instance of database objects, then the connection should only be 
	// released when the last database instance using the connection is deleted
	freeDbConn = !pwxDb;
	SetupColumns();
	Initialize();
}  // Ccontact Constructor


void UserTable::Initialize()
{
	//id = 0;
	name[0] = 0;
	email[0] = 0;
	country[0] = 0;
	countryCode[0] = 0;
	city[0] = 0;
	connection[0] = 0;
	longitude = 0;
	latitude = 0;
	lastIP = 0;
	time = 0;
	corruption = 0;
	cycles = 0;
	traceRt = 0;
	isOnline = 0;
}  


UserTable::~UserTable()
{
	if (freeDbConn)
	{
		if (!wxDbFreeConnection(GetDb()))
		{
			wxString tStr;
			tStr = wxT("Unable to Free the UserTable data table handle\n\n");
			wxLogError(tStr);
		}
	}
}  


/*
* Handles setting up all the connections for the interface from the wxDbTable
* functions to interface to the data structure used to store records in 
* memory, and for all the column definitions that define the table structure
*/
void UserTable::SetupColumns()
{
	//SetColDefs ( 0,_T("ID"),DB_DATA_TYPE_INTEGER,&id,SQL_C_UBIGINT,sizeof(id),TRUE,TRUE);// Primary index
	SetColDefs ( 0,_T("NAME"),DB_DATA_TYPE_VARCHAR,name,SQL_C_CHAR,sizeof(name),TRUE,TRUE);  
	SetColDefs ( 1,_T("EMAIL"),DB_DATA_TYPE_VARCHAR,email,SQL_C_CHAR,sizeof(email),FALSE,TRUE);
	SetColDefs ( 2,_T("COUNTRY"),DB_DATA_TYPE_VARCHAR,country,SQL_C_CHAR,sizeof(country),FALSE,TRUE);
	SetColDefs ( 3,_T("COUNTRY_CODE"),DB_DATA_TYPE_VARCHAR,countryCode,SQL_C_CHAR,sizeof(countryCode),FALSE,TRUE);
	SetColDefs ( 4,_T("CITY"),DB_DATA_TYPE_VARCHAR,city,SQL_C_CHAR,sizeof(city),FALSE,TRUE);
	SetColDefs ( 5,_T("CONNECTION"),DB_DATA_TYPE_VARCHAR,connection,SQL_C_CHAR,sizeof(connection),FALSE,TRUE);
	SetColDefs ( 6,_T("LONGITUDE"),DB_DATA_TYPE_FLOAT,&longitude,SQL_C_FLOAT,sizeof(longitude),FALSE,TRUE);
	SetColDefs ( 7,_T("LATITUDE"),DB_DATA_TYPE_FLOAT,&latitude,SQL_C_FLOAT,sizeof(latitude),FALSE,TRUE);
	SetColDefs ( 8,_T("LAST_IP"),DB_DATA_TYPE_INTEGER,&lastIP,SQL_INTEGER,sizeof(lastIP),FALSE,TRUE);
	SetColDefs ( 9,_T("ONLINE_TIME"),DB_DATA_TYPE_INTEGER,&time,SQL_INTEGER,sizeof(time),FALSE,TRUE);
	SetColDefs ( 10,_T("CORRUPTION"),DB_DATA_TYPE_INTEGER,&corruption,SQL_INTEGER,sizeof(corruption),FALSE,TRUE);
	SetColDefs ( 11,_T("CYCLES"),DB_DATA_TYPE_INTEGER,&cycles,SQL_INTEGER,sizeof(cycles),FALSE,TRUE);
	SetColDefs ( 12,_T("TRACEROUTE"),DB_DATA_TYPE_INTEGER,&traceRt,SQL_INTEGER,sizeof(traceRt),FALSE,TRUE);
	SetColDefs ( 13,_T("IS_ONLINE"),DB_DATA_TYPE_INTEGER,&isOnline,SQL_INTEGER,sizeof(isOnline),FALSE,TRUE);

}  // UserTable::SetupColumns

/*
* Having a function to do a query on the primary key (and possibly others) is
* very efficient and tighter coding so that it is available where ever the object
* is.  Great for use with multiple tables when not using views or outer joins
*/
bool UserTable::FetchByName(const wxString &name)
{
	//ClearMemberVars();
	whereStr.Printf("NAME = '%s'",name.c_str());
	//whereStr = _T("NAME = 'ben'");
	SetWhereClause((const char *)whereStr.c_str());
	//wxASSERT(GetWhereClause() == whereStr && "bogus!");
	//SetWhereClause(whereStr.c_str());
	//SetOrderByClause(wxT(""));

	if (!Query())
		return(FALSE);

	// Fetch the record
	bool b = GetNext();
	return(b);
} 

bool UserTable::IsNameFree(const wxString &username)
{
	ClearMemberVars();
	wxStrcpy(name, username);
	//name.Printf(wxT("%s"),username.c_str());
	if (!QueryOnKeyFields())
		return TRUE;
	return !GetNext();
}

