#include "Datenbank.h"

// Inhalt der HSDatenbank Klasse aus Datenbank.h
// Konstruktor
HSDatenbank::HSDatenbank( InitDatei *zIni )
{
	if( !zIni->wertExistiert( "DBBenutzer" ) )
		zIni->addWert( "DBBenutzer", "historieserveru" );
	if( !zIni->wertExistiert( "DBPasswort" ) )
		zIni->addWert( "DBPasswort", "LTHistorieServerPW" );
	if( !zIni->wertExistiert( "DBName" ) )
		zIni->addWert( "DBName", "koljadb" );
	if( !zIni->wertExistiert( "DBIP" ) )
		zIni->addWert( "DBIP", "127.0.0.1" );
	if( !zIni->wertExistiert( "DBPort" ) )
		zIni->addWert( "DBPort", "5432" );
	datenbank = new Datenbank( zIni->zWert( "DBBenutzer" )->getText(), zIni->zWert( "DBPasswort" )->getText(),
							   zIni->zWert( "DBName" )->getText(), zIni->zWert( "DBIP" )->getText(),
							   (unsigned short)TextZuInt( zIni->zWert( "DBPort" )->getText(), 10 ) );
	InitializeCriticalSection( &cs );
	ref = 1;
}

// Destruktor
HSDatenbank::~HSDatenbank()
{
	datenbank->release();
	DeleteCriticalSection( &cs );
}

// nicht constant
void HSDatenbank::lock()
{
	EnterCriticalSection( &cs );
}

void HSDatenbank::unlock()
{
	LeaveCriticalSection( &cs );
}

int HSDatenbank::istAdministrator( const char *name, const char *passwort )
{
	Text *befehl = new Text( "SELECT id FROM benutzer WHERE name = '" );
	Text n( name );
	n.ersetzen( "'", "''" );
	befehl->append( (char*)n );
	befehl->append( "' AND passwort = '" );
	Text p( passwort );
	p.ersetzen( "'", "''" );
	befehl->append( (char*)p );
	befehl->append( "'" );
	lock();
	datenbank->befehl( befehl->getText() );
	Result res = datenbank->getResult();
	unlock();
	befehl->release();
	int ret = 0;
	if( res.zeilenAnzahl > 0 )
		ret = TextZuInt( res.values[ 0 ].getText(), 10 );
	res.destroy();
	return ret;
}

bool HSDatenbank::adminHatRecht( int id, int recht )
{
	Text *befehl = new Text( "SELECT * FROM benutzer_rechte WHERE benutzer_id = " );
	befehl->append( id );
	befehl->append( " AND rechte_id = " );
	befehl->append( recht );
	lock();
	datenbank->befehl( befehl->getText() );
	int ret = datenbank->getZeilenAnzahl();
	unlock();
	befehl->release();
	return ret != 0;
}

bool HSDatenbank::proveKlient( int num, int sNum )
{
	Text *befehl = new Text( "SELECT * FROM server_historie_clients WHERE server_historie_id = " );
	befehl->append( sNum );
	befehl->append( " AND client_id = " );
	befehl->append( num );
	lock();
	datenbank->befehl( befehl->getText() );
	Result res = datenbank->getResult();
	unlock();
	befehl->release();
	bool ret = 0;
	if( res.zeilenAnzahl == 1 )
		ret = 1;
	res.destroy();
	return ret;
}

Text *HSDatenbank::getKlientKey( int cId )
{
	lock();
	if( !datenbank->befehl( Text( "SELECT schluessel FROM clients WHERE id = " ) += cId ) )
	{
		unlock();
		return 0;
	}
	Result res = datenbank->getResult();
	unlock();
	if( !res.zeilenAnzahl )
	{
		res.destroy();
		return 0;
	}
	Text *ret = new Text( res.values[ 0 ].getText() );
	res.destroy();
	return ret;
}

void HSDatenbank::unregisterKlient( int num, int sNum )
{
	Text *befehl = new Text( "DELETE FROM server_historie_clients WHERE client_id = " );
	befehl->append( num );
	befehl->append( " AND server_historie_id = " );
	befehl->append( sNum );
	lock();
	datenbank->befehl( befehl->getText() );
	int za = datenbank->getZeilenAnzahl();
	unlock();
	if( za == 1 )
	{
		befehl->setText( "UPDATE server_historie SET clients = clients - 1 WHERE id = " );
		befehl->append( sNum );
		lock();
		datenbank->befehl( befehl->getText() );
		unlock();
	}
	befehl->release();
}

bool HSDatenbank::serverAnmelden( InitDatei *zIni )
{
	if( !zIni->wertExistiert( "ServerId" ) )
		zIni->addWert( "ServerId", "0" );
	if( !zIni->wertExistiert( "ServerName" ) )
		zIni->addWert( "ServerName", "Name" );
	if( !zIni->wertExistiert( "ServerPort" ) )
		zIni->addWert( "ServerPort", "49131" );
	if( !zIni->wertExistiert( "ServerIP" ) )
		zIni->addWert( "ServerIP", "127.0.0.1" );
	if( !zIni->wertExistiert( "AdminServerPort" ) )
		zIni->addWert( "AdminServerPort", "49130" );
	if( !zIni->wertExistiert( "Aktiv" ) )
		zIni->addWert( "Aktiv", "FALSE" );
	if( !zIni->wertExistiert( "MaxClients" ) )
		zIni->addWert( "MaxClients", "50" );
	if( !zIni->wertExistiert( "MaxSpiele" ) )
		zIni->addWert( "MaxSpiele", "150" );
	bool insert = 0;
	int id = *zIni->zWert( "ServerId" );
	if( id )
	{
		lock();
		if( !datenbank->befehl( Text( "SELECT id FROM server_historie WHERE id = " ) += id ) )
		{
			unlock();
			return 0;
		}
		int anz = datenbank->getZeilenAnzahl();
		unlock();
		insert = anz == 0;
		if( !insert )
		{
			lock();
			if( !datenbank->befehl( Text( "SELECT id FROM server_historie WHERE server_status_id = 1 AND id = " ) += id ) )
			{
				unlock();
				return 0;
			}
			int anz = datenbank->getZeilenAnzahl();
			unlock();
			if( !anz ) // Server läuft bereits
				return 0;
		}
	}
	if( insert )
	{ // Neuer Eintrag in Tabelle server_historie
		Text *befehl = new Text( "INSERT INTO server_historie( " );
		if( id )
			*befehl += "id, ";
		*befehl += "name, ip, port, admin_port, server_status_id, max_clients, max_spiele ) VALUES( ";
		if( id )
		{
			*befehl += id;
			*befehl += ", ";
		}
		*befehl += "'";
		*befehl += zIni->zWert( "ServerName" )->getText();
		*befehl += "', '";
		*befehl += zIni->zWert( "ServerIP" )->getText();
		*befehl += "', ";
		*befehl += zIni->zWert( "ServerPort" )->getText();
		*befehl += ", ";
		*befehl += zIni->zWert( "AdminServerPort" )->getText();
		*befehl += ", 1, ";
		*befehl += zIni->zWert( "MaxClients" )->getText();
		*befehl += ", ";
		*befehl += zIni->zWert( "MaxSpiele" )->getText();
		*befehl += " ) RETURNING id";
		lock();
		if( !datenbank->befehl( *befehl ) )
		{
			unlock();
			befehl->release();
			return 0;
		}
		Result res = datenbank->getResult();
		unlock();
		befehl->release();
		if( !res.zeilenAnzahl )
		{
			res.destroy();
			return 0;
		}
		zIni->setWert( "ServerId", res.values[ 0 ] );
		return 1;
	}
	else
	{ // Alten Eintrag aus Tabelle server_historie ändern
		Text *befehl = new Text( "UPDATE server_historie SET name = '" );
		*befehl += zIni->zWert( "ServerName" )->getText();
		*befehl += "', port = ";
		*befehl += zIni->zWert( "ServerPort" )->getText();
		*befehl += ", ip = '";
		*befehl += zIni->zWert( "ServerIP" )->getText();
		*befehl += "', max_clients = ";
		*befehl += zIni->zWert( "MaxClients" )->getText();
		*befehl += ", admin_port = ";
		*befehl += zIni->zWert( "AdminServerPort" )->getText();
		*befehl += ", max_spiele = ";
		*befehl += zIni->zWert( "MaxSpiele" )->getText();
		*befehl += " WHERE id = ";
		*befehl += id;
		lock();
		bool ret = datenbank->befehl( *befehl );
		unlock();
		befehl->release();
		return ret;
	}
}

bool HSDatenbank::setServerStatus( int id, int status )
{
	Text *befehl = new Text( "UPDATE server_historie SET server_status_id = " );
	*befehl += status;
	*befehl += "WHERE id = ";
	*befehl += id;
	lock();
	if( !datenbank->befehl( befehl->getText() ) )
	{
		unlock();
		befehl->release();
		return 0;
	}
	bool ret = datenbank->getZeilenAnzahl() != 0;
	unlock();
	befehl->release();
	return ret;
}

bool HSDatenbank::setMaxClients( int id, int maxC )
{
	Text *befehl = new Text( "UPDATE server_historie SET max_clients = " );
	befehl->append( maxC );
	befehl->append( " WHERE id = " );
	befehl->append( id );
	lock();
	if( !datenbank->befehl( befehl->getText() ) )
	{
		unlock();
		befehl->release();
		return 0;
	}
	bool ret = datenbank->getZeilenAnzahl() > 0;
	unlock();
	befehl->release();
	return ret;
}

bool HSDatenbank::setMaxSpiele( int id, int maxS )
{
	Text *befehl = new Text( "UPDATE server_historie SET max_spiele = " );
	befehl->append( maxS );
	befehl->append( " WHERE id = " );
	befehl->append( id );
	lock();
	if( !datenbank->befehl( befehl->getText() ) )
	{
		unlock();
		befehl->release();
		return 0;
	}
	bool ret = datenbank->getZeilenAnzahl() > 0;
	unlock();
	befehl->release();
	return ret;
}

int HSDatenbank::getAdminPort( int id )
{
	Text *befehl = new Text( "SELECT admin_port FROM server_historie WHERE id = " );
	befehl->append( id );
	lock();
	if( !datenbank->befehl( befehl->getText() ) )
	{
		unlock();
		befehl->release();
		return 0;
	}
	Result res = datenbank->getResult();
	unlock();
	befehl->release();
	if( !res.zeilenAnzahl )
	{
		res.destroy();
		return 0;
	}
	int ret = res.values[ 0 ];
	res.destroy();
	return ret;
}

bool HSDatenbank::serverIstNichtPausiert( int id )
{
	Text *befehl = new Text( "SELECT server_status_id FROM server_historie WHERE id = " );
	befehl->append( id );
	lock();
	if( !datenbank->befehl( befehl->getText() ) )
	{
		unlock();
		befehl->release();
		return 0;
	}
	Result res = datenbank->getResult();
	unlock();
	befehl->release();
	if( !res.zeilenAnzahl )
	{
		res.destroy();
		return 0;
	}
	bool ret = (int)res.values[ 0 ] == 3;
	res.destroy();
	return ret;
}

bool HSDatenbank::getSpielServerPortIp( int id, short *port, Text *ip )
{
	lock();
	if( !datenbank->befehl( Text( "SELECT admin_port, ip FROM server_spiel WHERE id = " ) += id ) )
	{
		unlock();
		return 0;
	}
	Result res = datenbank->getResult();
	unlock();
	if( !res.zeilenAnzahl )
	{
		res.destroy();
		return 0;
	}
	*port = (short)(int)res.values[ 0 ];
	*ip = res.values[ 1 ].getText();
	res.destroy();
	return 1;
}

bool HSDatenbank::istSpielHistorieFrei( int id )
{
	lock();
	if( !datenbank->befehl( Text( "SELECT * FROM server_historie_spiel WHERE spiel_id = " ) += id ) )
	{
		unlock();
		return 0;
	}
	bool ret = datenbank->getZeilenAnzahl() == 0;
	unlock();
	return ret;
}

bool HSDatenbank::addSpielHistorie( int server, int spiel )
{
	Text *befehl = new Text( "INSERT INTO server_historie_spiel( spiel_id, server_historie_id ) VALUES( " );
	*befehl += spiel;
	*befehl += ", ";
	*befehl += server;
	*befehl += " )";
	lock();
	if( !datenbank->befehl( *befehl ) )
	{
		unlock();
		befehl->release();
		return 0;
	}
	unlock();
	befehl->release();
	lock();
	if( !datenbank->befehl( Text( "UPDATE server_historie SET spiele = spiele + 1 WHERE id = " ) += server ) )
	{
		unlock();
		return 0;
	}
	unlock();
	return 1;
}

// constant
Text *HSDatenbank::getLetzterFehler() const
{
	return datenbank->getLetzterFehler();
}

// Reference Counting
HSDatenbank *HSDatenbank::getThis()
{
	ref++;
	return this;
}

HSDatenbank *HSDatenbank::release()
{
	ref--;
	if( !ref )
		delete this;
	return 0;
}