#include "TSqliteDatabase.h"

int TSqliteDatabase::Initiate()
{
	// Save Information
	this->mDatabaseFile	= mSettings->getStr("sqlite3_database");

	// Connect to Database
	int err = sqlite3_open_v2(mDatabaseFile.text(), &mDatabase, SQLITE_OPEN_READWRITE, 0);
	if (err == SQLITE_CANTOPEN)
	{
		err = sqlite3_open(mDatabaseFile.text(), &mDatabase);
		if (err == SQLITE_OK)
			CreateDatabase();
	}
	
	SqlResult result;
	this->query("SELECT * FROM `graal2_accounts`", &result);
	this->Output_SqlResult(result);
	return err;
}

void TSqliteDatabase::CreateDatabase()
{
	this->query("CREATE TABLE IF NOT EXISTS graal2_accounts (account_id INTEGER PRIMARY KEY AUTOINCREMENT, account_name varchar(100) NOT NULL, account_password varchar(32) NOT NULL, account_salt int(11) NOT NULL, profile_name varchar(100) NULL, profile_age int(11) NULL, profile_gender varchar(10) NULL, profile_country varchar(32) NULL, profile_icq varchar(32) NULL, profile_email varchar(255) NULL, profile_url varchar(255) NULL, profile_hangout varchar(100) NULL, profile_quote varchar(255) NULL);");
	this->query("CREATE TABLE IF NOT EXISTS graal2_accounts_bans (accounts_ban_id INTEGER PRIMARY KEY AUTOINCREMENT, accounts_ban_account int(11) NOT NULL, accounts_ban_ipaddress varchar(40) NULL, accounts_ban_status tinyint(1) NULL, accounts_ban_time timestamp NOT NULL default CURRENT_TIMESTAMP, accounts_ban_server varchar(60) NOT NULL, accounts_ban_for varchar(255) NULL, accounts_ban_reason varchar(255) NULL);");
	this->query("CREATE TABLE IF NOT EXISTS graal2_guilds (guild_id INTEGER PRIMARY KEY AUTOINCREMENT, guild_name varchar(60) NOT NULL default '', guild_restrictnick tinyint(1) NOT NULL default '1', guild_status tinyint(1) NOT NULL default '0', owner_id int(11) NOT NULL default '0');");
	this->query("CREATE TABLE IF NOT EXISTS graal2_guilds_members (members_id INTEGER PRIMARY KEY AUTOINCREMENT, guild_id int(11) NOT NULL default '0', player_id int(11) NOT NULL default '0', player_nickname varchar(200) NULL default '');");
	this->query("CREATE TABLE IF NOT EXISTS graal2_serverlist (server_id INTEGER PRIMARY KEY AUTOINCREMENT, server_name varchar(60) NOT NULL, server_ip varchar(60) NOT NULL, server_port int(11) NOT NULL, server_playercount int(11) NOT NULL, server_maxplayers int(11) NOT NULL, server_description varchar(255) NULL, server_url varchar(255) NULL);");
}

int TSqliteDatabase::CreateAccount(const CString& pAccountName, const CString& pPassword)
{
	// Valid Account?
	if (pAccountName.length() < 4 || pAccountName.length() > 32)
		return CRACCT_INVACCT;

	// Valid Password
	if (pPassword.length() < 4 || pPassword.length() > 16)
		return CRACCT_INVPASS;

	// Account Exists?
	if (AccountExists(pAccountName))
		return CRACCT_EXISTS;

	// Create Account.. yay
	CString salt = GenerateHash(4);
	if (query(CString("INSERT INTO `graal2_accounts` ('account_name', 'account_password', 'account_salt') VALUES ('") << pAccountName.escape() << "', '" << CalculateMD5(CalculateMD5(pPassword) << salt).escape() << "', '" << salt.escape() << "')") != SQLITE_OK)
		return CRACCT_INVACCT;

	// Created
	return CRACCT_SUCCESS;
}

int TSqliteDatabase::VerifyAccount(CString& pAccountName, const CString& pPassword, bool pFromServer)
{
	return 1;
}

// - Last Sql Error - //
const char * TSqliteDatabase::error()
{
	return sqlite3_errmsg(mDatabase);
}

// - Process Query - //
int processQuery(void *pParam, int argc, char **argv, char **azColName)
{
	SqlRow res;
	SqlResult *list = (SqlResult *)pParam;
	for (int i = 0; i < argc; i++)
		res[azColName[i]] = argv[i];
	list->push_back(res);
	return 0;
}

// - Execute Sql Query - //
int TSqliteDatabase::query(const CString& pQuery, SqlResult *pResult)
{
	if (pResult != 0)
		pResult->clear();
	return sqlite3_exec(mDatabase, pQuery.text(), processQuery, pResult, 0);
}

#ifdef RUCOOL
#include "TSqliteDatabase.h"

/*
	Overrided Functions
*/
int TSqliteDatabase::Initiate()
{
	return (!this->connect(mSettings->getStr("sqlite3_database")));
}

bool TSqliteDatabase::AccountExists(const CString& pAccountName)
{
	// Invalid Account
	if (pAccountName.isEmpty())
		return false;

	// Query
	CString query = CString() << "SELECT account FROM `" << mSettings->getStr("userlist") << "` WHERE account='" << pAccountName.escape() << "' LIMIT 1";
	std::vector<CString> result;
	this->query(query, &result);

	// Return Exists
	return (result.size() != 0);
}

int TSqliteDatabase::CreateAccount(const CString& pAccountName, const CString& pPassword)
{
	// Valid Account?
	if (pAccountName.length() < 4 || pAccountName.length() > 32)
		return CRACCT_INVACCT;

	// Valid Password
	if (pPassword.length() < 4 || pPassword.length() > 16)
		return CRACCT_INVPASS;

	// Account Exists?
	if (AccountExists(pAccountName))
		return CRACCT_EXISTS;

	// Create Account.. yay
	
	// Account Exists
	return CRACCT_SUCCESS;
}

int TSqliteDatabase::VerifyAccount(CString& pAccountName, const CString& pPassword, bool pFromServer)
{
	// make sure its not empty.
	if (pAccountName.isEmpty())
		return ACCSTAT_INVALID;

	// definitions
	CString query;
	std::vector<CString> result;
	CString password(pPassword);

	// See if we should try a secure login.
	int ret = ACCSTAT_INVALID;

	// Either the secure login failed or we didn't try a secure login.
	// Try the old login method.
	if (ret == ACCSTAT_INVALID)
	{
		result.clear();
		query = CString() << "SELECT password, salt, activated, banned, account FROM `" << mSettings->getStr("userlist") << "` WHERE account='" << pAccountName.escape() << "' AND password=" << "MD5(CONCAT(MD5('" << pPassword.escape() << "'), `salt`)) LIMIT 1";
		this->query(query, &result);

		// account/password correct?
		if (result.size() == 0)
			return ACCSTAT_INVALID;

		// activated?
		if (result.size() < 3 || result[2] == "0")
			return ACCSTAT_NONREG;

		// banned?
		if (result.size() > 3 && result[3] == "1")
			return ACCSTAT_BANNED;

		// Get the case-sensitive account name.
		if (result.size() > 4)
			pAccountName = result[4];

		// passed all tests :)
		return ACCSTAT_NORMAL;
	}

	return ACCSTAT_INVALID;
}

int TSqliteDatabase::VerifyGuild(const CString& pGuildName, const CString& pAccountName, const CString& pNickName)
{
	return 0;
}

int TSqliteDatabase::VerifyIpBan(const CString& pIpAddress, int pType)
{
	/*
	for (std::vector<CString>::const_iterator i = mIpBans[pType].begin(); i != mIpBans[pType].end(); ++i)
	{
		if (pIpAddress.match(*i))
			return 1;
	}
	*/

	return 0;
}

/*
	Private Functions
*/
bool TSqliteDatabase::connect(const CString& pDatabaseFile)
{
	// Save Information
	this->mDatabaseFile	= pDatabaseFile;

	// Open Database
	return (sqlite3_open(pDatabaseFile.text(), &mDatabase) == 0);
}

const char * TSqliteDatabase::error()
{
	return 0; //sqlite3_error(mMySql);
}

int TSqliteDatabase::query(const CString& pQuery, std::vector<CString> *pResult)
{
	/*
	// run query
	if (mysql_query(mMySql, pQuery.text()))
		return 0;

	// no result wanted?
	if (pResult != 0)
	{
		// store result
		if (!(mResult = mysql_store_result(mMySql)))
			return 0;

		// fetch row
		MYSQL_ROW row = mysql_fetch_row(mResult);
		unsigned long *lengths = mysql_fetch_lengths(mResult);
		if (lengths == 0 || row == 0)
		{
			mysql_free_result(mResult);
			return 0;
		}

		// empty old result
		pResult->clear();

		// Grab the full value and add it to the vector.
		for (unsigned int i = 0; i < mysql_num_fields(mResult); i++)
		{
			char* temp = new char[lengths[i] + 1];
			memcpy(temp, row[i], lengths[i]);
			temp[lengths[i]] = '\0';
			pResult->push_back(CString(temp));
			delete temp;
		}

		// cleanup
		mysql_free_result(mResult);
		return pResult->size();
	}
	else
		return 0;
	*/

	return 0;
}
#endif