#include "AnmeldungServer.h"
#include <iostream>
#include <Klient.h>
#include <Globals.h>

// Inhalt der AnmeldungServer Klasse aus AnmeldungServer.h
// Konstruktor 
AnmeldungServer::AnmeldungServer( InitDatei *zIni )
	: Thread()
{
	Network::Start( 100 );
	std::cout << "AS: Verbindung mit Datenbank wird hergestellt...\n";
	db = new ASDatenbank( zIni );
	klientAnzahl = 0;
	klients = new RCArray< ASKlient >();
	empfangen = 0;
	gesendet = 0;
	fehler = new Text();
	ini = zIni->getThis();
	id = *zIni->zWert( "ServerId" );
	server = new Server();
	aServer = new Server();
	std::cout << "AS: Starten des Admin Servers...\n";
	if( !aServer->verbinde( (unsigned short)TextZuInt( ini->zWert( "AdminServerPort" )->getText(), 10 ), 10 ) )
	{
		std::cout << "AS: Der Admin Server konnte nicht gestartet werden. Das Programm wird beendet.\n";
		exit( 1 );
	}
	db->setServerStatus( id, 2 );
	end = 0;
	nichtPausiert = 0;
	InitializeCriticalSection( &cs );
	ref = 1;
	if( zIni->zWert( "Aktiv" )->istGleich( "TRUE" ) )
	{
		serverStarten();
		serverFortsetzen();
	}
}

// Destruktor 
AnmeldungServer::~AnmeldungServer()
{
	fehler->release();
	server->trenne();
	server->release();
	aServer->trenne();
	aServer->release();
	if( klients )
		klients->release();
	ini->release();
	db->release();
	DeleteCriticalSection( &cs );
}

// nicht constant 
void AnmeldungServer::runn()
{
	while( !end )
	{
		SKlient *klient;
		klient = aServer->getKlient();
		if( end && klient )
		{
			klient->trenne();
			klient = klient->release();
			Sleep( 1000 );
			return;
		}
		if( !klient )
			return;
		ASAKlient *clHandle = new ASAKlient( klient, getThis() );
		clHandle->start();
	}
}

void AnmeldungServer::thread()
{
	while( 1 )
	{
		SKlient *klient;
		klient = server->getKlient();
		if( !klient )
			break;
		Framework::getThreadRegister()->cleanUpClosedThreads();
		ASKlient *clHandle = new ASKlient( klient, getThis() );
		EnterCriticalSection( &cs );
		klients->set( clHandle, klientAnzahl );
		klientAnzahl++;
		LeaveCriticalSection( &cs );
		clHandle->start();
	}
}

void AnmeldungServer::close()
{
	db->setServerStatus( id, 1 );
	server->trenne();
#ifdef WIN32
	warteAufThread( 1000 );
#endif
	EnterCriticalSection( &cs );
	for( int i = 0; i < klientAnzahl; i++ )
		klients->z( i )->absturz();
	klients = klients->release();
	klientAnzahl = 0;
	LeaveCriticalSection( &cs );
	ende();
	run = 0;
	end = 1;
	Klient *klient = new Klient();
	klient->verbinde( aServer->getPort(), "127.0.0.1" );
	Sleep( 500 );
	aServer->trenne();
	klient->release();
}

bool AnmeldungServer::serverStarten()
{
	if( nichtPausiert )
	{
		fehler->setText( "Der Server konnte nicht gestartet werden: Der Server läuft bereits." );
		return 0;
	}
	if( server )
		server->release();
	server = new Server();
	if( server->verbinde( (unsigned short)TextZuInt( ini->zWert( "ServerPort" )->getText(), 10 ), 10 ) )
	{
		nichtPausiert = 1;
		start();
		return 1;
	}
	else
	{
		serverBeenden();
		fehler->setText( "Der Server konnte nicht gestartet werden: Eventuell ist der Port in benutzung." );
		return 0;
	}
}

bool AnmeldungServer::serverPause()
{
	if( !nichtPausiert )
	{
		fehler->setText( "Der Server konnte nicht pausiert werden: Der Server läuft nicht." );
		return 0;
	}
	if( !db->setServerStatus( id, 2 ) )
	{
		fehler->setText( "Der Server konnte nicht pausiert werden: " );
		fehler->append( db->getLetzterFehler() );
		return 0;
	}
	return 1;
}

bool AnmeldungServer::serverFortsetzen()
{
	if( !nichtPausiert )
	{
		fehler->setText( "Der Server konnte nicht fortgesetzt werden: Der Server läuft nicht." );
		return 0;
	}
	if( !db->setServerStatus( id, 3 ) )
	{
		fehler->setText( "Der Server konnte nicht fortgesetzt werden: " );
		fehler->append( db->getLetzterFehler() );
		return 0;
	}
	return 1;
}

bool AnmeldungServer::serverBeenden()
{
	if( !nichtPausiert )
	{
		fehler->setText( "Der Server konnte nicht beendet werden: Der Server läuft nicht." );
		return 0;
	}
	if( db->serverIstNichtPausiert( id ) )
	{
		fehler->setText( "Der Server konnte nicht beendet werden: Der Server muss erst pausiert werden." );
		return 0;
	}
	nichtPausiert = 0;
	ende();
	if( server )
		server->trenne();
	return 1;
}

bool AnmeldungServer::setMaxKlients( int mc )
{
	if( !db->setMaxClients( id, mc ) )
	{
		fehler->setText( "Die maximale Anzahl der Clients konnte nicht gesetzt werden:\n" );
		fehler->append( db->getLetzterFehler() );
		return 0;
	}
	return 1;
}

bool AnmeldungServer::absturzKlient( int klientId )
{
	bool gefunden = 0;
	EnterCriticalSection( &cs );
	for( int i = 0; i < klientAnzahl; i++ )
	{
		if( klients->z( i )->getKlientNummer() == klientId )
		{
			klients->z( i )->absturz();
			klients->remove( i );
			klientAnzahl--;
			gefunden = 1;
			break;
		}
	}
	LeaveCriticalSection( &cs );
	return gefunden;
}

bool AnmeldungServer::removeKlient( ASKlient *zKlient )
{
	bool gefunden = 0;
	EnterCriticalSection( &cs );
	for( int i = 0; i < klientAnzahl; i++ )
	{
		if( klients->z( i ) == zKlient )
		{
			klients->remove( i );
			klientAnzahl--;
			gefunden = 1;
			break;
		}
	}
	LeaveCriticalSection( &cs );
	return gefunden;
}

void AnmeldungServer::addGesendet( int bytes )
{
	gesendet += bytes;
}

void AnmeldungServer::addEmpfangen( int bytes )
{
	empfangen += bytes;
}

// constant 
bool AnmeldungServer::istAn() const
{
	return db->serverIstNichtPausiert( id );
}

Server *AnmeldungServer::zServer() const
{
	return server;
}

ASDatenbank *AnmeldungServer::zDB() const
{
	return db;
}

bool AnmeldungServer::hatClients() const
{
	return klientAnzahl > 0;
}

int AnmeldungServer::getId() const
{
	return id;
}

char *AnmeldungServer::getLetzterFehler() const
{
	return fehler->getText();
}

char *AnmeldungServer::getIp() const
{
	return ini->zWert( "ServerIp" )->getText();
}

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

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


// Inhalt der ASAKlient Klasse aus AnmeldungServer.h
// Konstruktor 
ASAKlient::ASAKlient( SKlient *klient, AnmeldungServer *as )
	: Thread()
{
	this->klient = klient;
	unsigned char key[ 20 ] = { 208, 28, 97, 9, 169, 209, 137, 159, 123, 216, 202, 244, 86, 78, 172, 35, 26, 180, 113, 47 };
	klient->setSendeKey( (char*)key, 20 );
	klient->setEmpfangKey( (char*)key, 20 );
	name = new Text( "" );
	passwort = new Text( "" );
	adminId = 0;
	version = 0;
	this->as = as;
}

// Destruktor 
ASAKlient::~ASAKlient()
{
	klient->trenne();
	klient->release();
	as->release();
	name->release();
	passwort->release();
}

// nicht constant 
void ASAKlient::thread()
{
	while( 1 )
	{
		char c = 0;
		if( !klient->getNachrichtEncrypted( &c, 1 ) )
			break;
		else
		{
			bool br = 0;
			switch( c )
			{
			case 1: // Login
				if( 1 )
				{
					klient->sendeEncrypted( "\1", 1 );
					char nLen = 0;
					klient->getNachrichtEncrypted( &nLen, 1 );
					char *n = new char[ nLen + 1 ];
					n[ (int)nLen ] = 0;
					if( nLen )
						klient->getNachrichtEncrypted( n, nLen );
					char pLen = 0;
					klient->getNachrichtEncrypted( &pLen, 1 );
					char *p = new char[ pLen + 1 ];
					p[ (int)pLen ] = 0;
					if( pLen )
						klient->getNachrichtEncrypted( p, pLen );
					int adminId = as->zDB()->istAdministrator( n, p );
					if( adminId )
					{
						klient->sendeEncrypted( "\1", 1 );
						name->setText( n );
						passwort->setText( p );
						this->adminId = adminId;
					}
					else
						errorZuKlient( "Falsche Kombination aus Name und Passwort." );
					delete[] n;
					delete[] p;
				}
				break;
			case 2: // Logout
				adminId = 0;
				name->setText( "" );
				passwort->setText( "" );
				klient->sendeEncrypted( "\1", 1 );
				break;
			case 3: // Trennen
				br = 1;
				klient->sendeEncrypted( "\1", 1 );
				break;
			case 4: // Server starten
				if( !adminId )
					errorZuKlient( "Du musst dich einloggen." );
				else
				{
					if( as->zDB()->adminHatRecht( adminId, Admin_Recht::ASStarten ) )
					{
						if( !as->serverStarten() )
						{
							Text *err = new Text();
							err->append( as->getLetzterFehler() );
							errorZuKlient( err->getText() );
							err->release();
						}
						else
							klient->sendeEncrypted( "\1", 1 );
					}
					else
						errorZuKlient( "Du bist nicht berechtigt den Server zu starten." );
				}
				break;
			case 5: // Server beenden
				if( !adminId )
					errorZuKlient( "Du musst dich einloggen." );
				else
				{
					if( as->zDB()->adminHatRecht( adminId, Admin_Recht::ASBeenden ) )
					{
						if( as->serverBeenden() )
							klient->sendeEncrypted( "\1", 1 );
						else
						{
							Text *err = new Text();
							err->append( as->getLetzterFehler() );
							errorZuKlient( err->getText() );
							err->release();
						}
					}
					else
						errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
				}
				break;
			case 6: // Programm Schließen
				if( !adminId )
					errorZuKlient( "Du musst dich einloggen." );
				else
				{
					bool ok = 0;
					if( as->isRunning() )
					{
						if( as->zDB()->adminHatRecht( adminId, Admin_Recht::ASBeenden ) )
						{
							if( as->serverBeenden() )
								ok = 1;
							else
							{
								Text *err = new Text();
								err->append( as->getLetzterFehler() );
								errorZuKlient( err->getText() );
								err->release();
							}
						}
						else
							errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
					}
					else
						ok = 1;
					if( ok && as->hatClients() )
					{
						errorZuKlient( "Es sind noch Klients Online. Bitte versuche es später erneut." );
						break;
					}
					if( ok )
					{
						klient->sendeEncrypted( "\1", 1 );
						std::cout << "AS: Der Server wird von Benutzer " << adminId << " heruntergefahren.\n";
						as->close();
						br = 1;
					}
				}
				break;
			case 7: // Progtamm abstürzen
				if( !adminId )
					errorZuKlient( "Du musst dich einloggen." );
				else
				{
					bool ok = 0;
					if( as->isRunning() )
					{
						if( as->zDB()->adminHatRecht( adminId, Admin_Recht::ASBeenden ) )
						{
							as->serverBeenden();
							ok = 1;
						}
						else
							errorZuKlient( "Du bist nicht berechtigt den Server zu beenden." );
					}
					else
						ok = 1;
					if( ok )
					{
						klient->sendeEncrypted( "\1", 1 );
						std::cout << "AS: Der Server wurde von Benutzer " << adminId << " terminiert.\n";
						as->close();
						br = 1;
					}
				}
				break;
			case 8: // Status Frage
				if( 1 )
				{
					char status = 0;
					if( as->isRunning() )
					{
						status = 1;
						if( as->istAn() )
							status = 2;
					}
					klient->sendeEncrypted( "\1", 1 );
					klient->sendeEncrypted( &status, 1 );
				}
				break;
			case 9: // Server pausieren
				if( !adminId )
					errorZuKlient( "Du musst dich einloggen." );
				else
				{
					klient->sendeEncrypted( "\1", 1 );
					char pause = 0;
					klient->getNachrichtEncrypted( &pause, 1 );
					if( as->zDB()->adminHatRecht( adminId, Admin_Recht::ASPausieren ) )
					{
						bool ok = 0;
						if( pause )
							ok = as->serverPause();
						else
							ok = as->serverFortsetzen();
						if( ok )
							klient->sendeEncrypted( "\1", 1 );
						else
						{
							Text *err = new Text();
							err->append( as->getLetzterFehler() );
							errorZuKlient( err->getText() );
							err->release();
						}
					}
					else
					{
						if( pause )
							errorZuKlient( "Du bist nicht berechtigt den Server zu pausieren." );
						else
							errorZuKlient( "Du bist nicht berechtigt den Server fortzusetzen." );
					}
				}
				break;
			case 0xA: // maximale Anzahl der Clients setzen
				if( !adminId )
					errorZuKlient( "Du musst dich einloggen." );
				else
				{
					klient->sendeEncrypted( "\1", 1 );
					int maxC = 0;
					klient->getNachrichtEncrypted( (char*)&maxC, 4 );
					if( as->zDB()->adminHatRecht( adminId, Admin_Recht::ASMCChange ) )
					{
						if( as->setMaxKlients( maxC ) )
							klient->sendeEncrypted( "\1", 1 );
						else
						{
							Text *err = new Text();
							err->append( as->getLetzterFehler() );
							errorZuKlient( err->getText() );
							err->release();
						}
					}
					else
						errorZuKlient( "Du bist nicht berechtigt die maximale Anzahl der Clients zu verändern." );
				}
				break;
            case 0xC: // klient absturtz
                if( 1 )
                {
                    klient->sendeEncrypted( "\1", 1 );
                    int klientId = 0;
                    klient->getNachrichtEncrypted( (char*)&klientId, 4 );
                    if( klientId && as->absturzKlient( klientId ) )
                        klient->sendeEncrypted( "\1", 1 );
                    else
                        klient->sendeEncrypted( "\0", 1 );
                }
                break;
			default:
				errorZuKlient( "Unbekannte Nachricht!" );
				break;
			}
			if( br )
				break;
			as->addEmpfangen( klient->getDownloadBytes( 1 ) );
			as->addGesendet( klient->getUploadBytes( 1 ) );
		}
	}
	as->addEmpfangen( klient->getDownloadBytes( 1 ) );
	as->addGesendet( klient->getUploadBytes( 1 ) );
	delete this;
}

void ASAKlient::errorZuKlient( const char *nachricht ) const // sendet eine Fehlernachricht zum Klient
{
	klient->sendeEncrypted( "\3", 1 );
	char len = (char)textLength( nachricht );
	klient->sendeEncrypted( &len, 1 );
	klient->sendeEncrypted( nachricht, len );
}


// Inhalt der ASKlient aus AnmeldungServer.h
// Konstruktor
ASKlient::ASKlient( SKlient *klient, AnmeldungServer *as )
	: Thread()
{
	this->klient = klient;
	unsigned char key[ 20 ] = { 158, 10, 37, 155, 117, 58, 28, 197, 132, 76, 252, 83, 84, 222, 11, 125, 240, 218, 25, 201 };
	klient->setSendeKey( (char*)key, 20 );
	klient->setEmpfangKey( (char*)key, 20 );
	klientNummer = 0;
	this->as = as;
	accountId = 0;
	ref = 1;
}

// Destruktor 
ASKlient::~ASKlient()
{
	klient->release();
	as->release();
}

// nicht constant 
void ASKlient::absturz()
{
	ende();
	klient->trenne();
	as->zDB()->unregisterKlient( klientNummer, as->getId() );
}

void ASKlient::thread()
{
	while( 1 )
	{
		char c = 0;
		if( !klient->getNachrichtEncrypted( &c, 1 ) )
			break;
		else
		{
			bool br = 0;
			switch( c )
			{
			case 1: // Klient identifikation
				klient->getNachrichtEncrypted( (char*)&klientNummer, 4 );
				if( !as->zDB()->proveKlient( klientNummer, as->getId() ) )
				{
					klientNummer = 0;
					errorZuKlient( "Du bist nicht für diesen Server eingetragen" );
				}
				else
				{
					accountId = as->zDB()->getAccountId( klientNummer );
					if( accountId )
					{
						Text *key = as->zDB()->getKlientKey( klientNummer );
						if( !key )
							errorZuKlient( "Es konnte kein Schlüssel ermittelt werden." );
						else
						{
							klient->sendeEncrypted( "\1", 1 );
							klient->setEmpfangKey( *key, key->getLength() );
							klient->setSendeKey( *key, key->getLength() );
							key->release();
						}
					}
					else
					{
						klientNummer = 0;
						errorZuKlient( "Du bist nicht eingeloggt." );
					}
				}
				break;
			case 2: // Main / Erhaltung Server message
				if( 1 )
				{
					char befehl = 0;
					klient->getNachrichtEncrypted( &befehl, 1 );
					switch( befehl )
					{
					case 2: // klient absturtz
						if( 1 )
						{
							int klientId = 0;
							klient->getNachrichtEncrypted( (char*)&klientId, 4 );
							if( klientId && as->absturzKlient( klientId ) )
								klient->sendeEncrypted( "\1", 1 );
							else
								klient->sendeEncrypted( "\0", 1 );
						}
						break;
					default:
						errorZuKlient( "Befehl nicht bekannt!" );
						break;
					}
				}
				break;
			case 3: // Verbindungsende
				br = 1;
				klient->sendeEncrypted( "\1", 1 );
				break;
			case 4: // unregister Klient
				if( !klientNummer )
				{
					errorZuKlient( "Du bist nicht Identifiziert." );
					break;
				}
				as->zDB()->unregisterKlient( klientNummer, as->getId() );
				klient->sendeEncrypted( "\1", 1 );
				break;
			case 5: // gruppe erstellen
				if( 1 )
				{
					if( !klientNummer )
					{
						errorZuKlient( "Du bist nicht Identifiziert." );
						break;
					}
					klient->sendeEncrypted( "\1", 1 );
					int karteId = 0;
					klient->getNachrichtEncrypted( (char*)&karteId, 4 );
					int gruppeId = 0;
					int ret = as->zDB()->gruppeErstellen( accountId, karteId, &gruppeId );
					switch( ret )
					{
					case 0:
						errorZuKlient( "Du bist nicht eingeloggt." );
						break;
					case 1:
						errorZuKlient( "Du wurdest bereits einem Spiel zugeordnet." );
						break;
					case 2:
						errorZuKlient( "Du bist in einem anderen noch laufendem Spiel. Spiele es zu Ende." );
						break;
					case 3:
						errorZuKlient( "Du bist in einer anderen Gruppe." );
						break;
					case 4:
						errorZuKlient( "Du bist bereits in der Warteschlange." );
						break;
					case 5:
						errorZuKlient( "Die Karte ist zur Zeit nicht spielbar." );
						break;
					case 6:
						errorZuKlient( "Unbekannter Fehler." );
						break;
					case 7:
						klient->sendeEncrypted( "\1", 1 );
						klient->sendeEncrypted( (char*)&gruppeId, 4 );
						break;
					}
				}
				break;
			case 6: // gruppe betreten
				if( 1 )
				{
					if( !klientNummer )
					{
						errorZuKlient( "Du bist nicht Identifiziert." );
						break;
					}
					klient->sendeEncrypted( "\1", 1 );
					int gruppeId = 0;
					klient->getNachrichtEncrypted( (char*)&gruppeId, 4 );
					if( as->zDB()->gruppeIstInWarteschlange( gruppeId ) )
					{
						errorZuKlient( "Die Gruppe befindet sich bereits in der Warteschlange." );
						break;
					}
					if( !as->zDB()->gruppeSpielerIstEingeladen( gruppeId, accountId ) )
					{
						errorZuKlient( "Du bist nicht mehr eingeladen." );
						break;
					}
					int anzahl = 0;
					Array< int > *accIds = new Array< int >();
					as->zDB()->getSpielerInGruppe( gruppeId, accIds, &anzahl );
					int res = as->zDB()->gruppeBetreten( accountId, gruppeId );
					switch( res )
					{
					case 0:
						errorZuKlient( "Du bist nicht eingeloggt." );
						break;
					case 1:
						errorZuKlient( "Du wurdest bereits einem Spiel zugeordnet." );
						break;
					case 2:
						errorZuKlient( "Du bist in einem anderen noch laufendem Spiel. Spiele es zu Ende." );
						break;
					case 3:
						errorZuKlient( "Du bist in einer anderen Gruppe." );
						break;
					case 4:
						errorZuKlient( "Du bist bereits in der Warteschlange." );
						break;
					case 5:
						errorZuKlient( "Die Gruppe ist bereits in einem Spiel." );
						break;
					case 6:
						errorZuKlient( "Unbekannter Fehler." );
						break;
					case 7:
						if( 1 )
						{
							klient->sendeEncrypted( "\1", 1 );
							klient->sendeEncrypted( (char*)&anzahl, 4 );
							for( int i = 0; i < anzahl; i++ )
							{
								int id = accIds->get( i );
								if( id == accountId )
									continue;
								klient->sendeEncrypted( (char*)&id, 4 );
							}
							as->zDB()->gruppeEinladungAbbrechen( as->zDB()->getGruppeAdminId( gruppeId ), gruppeId, accountId );
							MsgWeiterleitung *weiter = new MsgWeiterleitung( accountId, as->getThis() );
							weiter->spielerBetrittGruppe( gruppeId );
							weiter->release();
						}
						break;
					}
					accIds->release();
				}
				break;
			case 7: // gruppe verlassen
				if( 1 )
				{
					if( !klientNummer )
					{
						errorZuKlient( "Du bist nicht Identifiziert." );
						break;
					}
					klient->sendeEncrypted( "\1", 1 );
					int gruppeId = 0;
					klient->getNachrichtEncrypted( (char*)&gruppeId, 4 );
					if( as->zDB()->gruppeIstInWarteschlange( gruppeId ) )
					{
						errorZuKlient( "Die Gruppe befindet sich bereits in der Warteschlange." );
						break;
					}
					int ret = as->zDB()->gruppeVerlassen( accountId, gruppeId );
					if( !ret )
						errorZuKlient( "Du kannst die gruppe momentan nicht mehr verlassen." );
					if( ret == 1 )
					{
						klient->sendeEncrypted( "\1", 1 );
						MsgWeiterleitung *weiter = new MsgWeiterleitung( accountId, as->getThis() );
						weiter->spielerLeavesGruppe( gruppeId );
						weiter->release();
					}
					if( ret == 2 )
						klient->sendeEncrypted( "\1", 1 );
					if( ret == 3 )
					{
						klient->sendeEncrypted( "\1", 1 );
						int adminId = as->zDB()->getGruppeAdminId( gruppeId );
						MsgWeiterleitung *weiter = new MsgWeiterleitung( accountId, as->getThis() );
						weiter->setGruppeAdmin( gruppeId, adminId );
						weiter->spielerLeavesGruppe( gruppeId );
						weiter->release();
					}
					if( ret == 4 )
					{
						klient->sendeEncrypted( "\1", 1 );
						Array< int > *spieler = new Array< int >();
						int anzahl = 0;
						MsgWeiterleitung *weiter = new MsgWeiterleitung( accountId, as->getThis() );
						if( as->zDB()->getSpielerInGruppe( gruppeId, spieler, &anzahl ) )
						{
							for( int i = 0; i < anzahl; i++ )
							{
								if( spieler->hat( i ) )
								{
									weiter->kickSpielerAusGruppe( spieler->get( i ), gruppeId );
									as->zDB()->gruppeVerlassen( spieler->get( i ), gruppeId );
								}
							}
						}
						spieler->release();
						weiter->release();
					}
				}
				break;
			case 9: // gruppe anmelden
				if( 1 )
				{
					if( !klientNummer )
					{
						errorZuKlient( "Du bist nicht Identifiziert." );
						break;
					}
					klient->sendeEncrypted( "\1", 1 );
					int gruppeId = 0;
					klient->getNachrichtEncrypted( (char*)&gruppeId, 4 );
					if( !as->zDB()->spielerBesitztKarte( accountId, as->zDB()->getGruppenKarte( gruppeId ) ) )
					{
						errorZuKlient( "Du besitzt entweder die Karte oder das Spiel nicht." );
						break;
					}
					if( as->zDB()->getGruppeSpielStarten( gruppeId ) && as->zDB()->getSpielerInGruppeAnzahl( gruppeId ) <= 1 )
					{
						errorZuKlient( "Es müssen mindestens 2 Spieler in der Gruppe vorhanden sein." );
						break;
					}
					if( as->zDB()->gruppeAnmelden( accountId, gruppeId ) )
					{
						klient->sendeEncrypted( "\1", 1 );
						MsgWeiterleitung *weiter = new MsgWeiterleitung( accountId, as->getThis() );
						weiter->gruppeAngemeldet( gruppeId );
						weiter->release();
					}
					else
						errorZuKlient( "Du kannst die Gruppe nicht anmelden." );
				}
				break;
			case 0xA: // gruppe abmelden
				if( 1 )
				{
					if( !klientNummer )
					{
						errorZuKlient( "Du bist nicht Identifiziert." );
						break;
					}
					klient->sendeEncrypted( "\1", 1 );
					int gruppeId = 0;
					klient->getNachrichtEncrypted( (char*)&gruppeId, 4 );
					if( as->zDB()->gruppeAbmelden( accountId, gruppeId ) )
					{
						klient->sendeEncrypted( "\1", 1 );
						MsgWeiterleitung *weiter = new MsgWeiterleitung( accountId, as->getThis() );
						weiter->gruppeAbgemeldet( gruppeId );
						weiter->release();
					}
					else
						errorZuKlient( "Du kannst die Gruppe nicht abmelden." );
					break;
				}
			case 0xB: // spieler einladen
				if( 1 )
				{
					if( !klientNummer )
					{
						errorZuKlient( "Du bist nicht Identifiziert." );
						break;
					}
					klient->sendeEncrypted( "\1", 1 );
					int gruppeId = 0;
					int zuAccountId = 0;
					klient->getNachrichtEncrypted( (char*)&zuAccountId, 4 );
					klient->getNachrichtEncrypted( (char*)&gruppeId, 4 );
					if( as->zDB()->gruppeIstInWarteschlange( gruppeId ) )
					{
						errorZuKlient( "Die Gruppe befindet sich bereits in der Warteschlange." );
						break;
					}
					if( as->zDB()->gruppeSpielerEinladen( accountId, zuAccountId, gruppeId ) )
					{
						MsgWeiterleitung *weiter = new MsgWeiterleitung( accountId, as->getThis() );
						if( weiter->spielEinladung( gruppeId, zuAccountId ) )
							klient->sendeEncrypted( "\1", 1 );
						else
						{
							if( weiter->zLetzterFehler()->getLength() )
								errorZuKlient( weiter->zLetzterFehler()->getText() );
							else
								errorZuKlient( "Fehler beim zuteilen der Einladung." );
						}
						weiter->release();
					}
					else
						errorZuKlient( "Du kannst diesen Spieler nicht einladen." );
				}
				break;
			case 0xC: // spieler kicken
				if( 1 )
				{
					if( !klientNummer )
					{
						errorZuKlient( "Du bist nicht Identifiziert." );
						break;
					}
					klient->sendeEncrypted( "\1", 1 );
					int gruppeId = 0;
					int zuAccountId = 0;
					klient->getNachrichtEncrypted( (char*)&zuAccountId, 4 );
					klient->getNachrichtEncrypted( (char*)&gruppeId, 4 );
					if( as->zDB()->gruppeIstInWarteschlange( gruppeId ) )
					{
						errorZuKlient( "Die Gruppe befindet sich bereits in der Warteschlange." );
						break;
					}
					if( as->zDB()->spielerKannKicken( accountId, gruppeId ) )
					{
						klient->sendeEncrypted( "\1", 1 );
						as->zDB()->gruppeVerlassen( zuAccountId, gruppeId );
						MsgWeiterleitung *weiter = new MsgWeiterleitung( zuAccountId, as->getThis() );
						weiter->kickSpielerAusGruppe( zuAccountId, gruppeId );
						weiter->spielerLeavesGruppe( gruppeId );
						weiter->release();
					}
					else
						errorZuKlient( "Du hast keine berechtigung diesen Spieler zu kicken." );
				}
				break;
			case 0xD: // gruppen Nachricht senden
				if( 1 )
				{
					if( !klientNummer )
					{
						errorZuKlient( "Du bist nicht Identifiziert." );
						break;
					}
					klient->sendeEncrypted( "\1", 1 );
					int gruppeId = 0;
					char key = 0;
					klient->getNachrichtEncrypted( (char*)&gruppeId, 4 );
					klient->getNachrichtEncrypted( &key, 1 );
					char *nachricht = new char[ key + 1 ];
					nachricht[ (int)key ] = 0;
					if( key )
						klient->getNachrichtEncrypted( nachricht, key );
					else
					{
						klient->sendeEncrypted( "\1", 1 );
						delete[] nachricht;
						break;
					}
					klient->sendeEncrypted( "\1", 1 );
					Text *message = as->zDB()->getAccountRufName( accountId );
					message->append( ": " );
					message->append( nachricht );
					delete[] nachricht;
					MsgWeiterleitung *weiter = new MsgWeiterleitung( accountId, as->getThis() );
					weiter->gruppenNachricht( gruppeId, message->getText() );
					weiter->release();
					message->release();
				}
				break;
			case 0xE: // spieler anmelden
				if( 1 )
				{
					if( !klientNummer )
					{
						errorZuKlient( "Du bist nicht Identifiziert." );
						break;
					}
					klient->sendeEncrypted( "\1", 1 );
					int karteId = 0;
					klient->getNachrichtEncrypted( (char*)&karteId, 4 );
					if( !as->zDB()->spielerBesitztKarte( accountId, karteId ) )
					{
						errorZuKlient( "Du besitzt entweder die Karte oder das Spiel nicht." );
						break;
					}
					int ret = as->zDB()->accountAnmelden( accountId, karteId );
					switch( ret )
					{
					case 0:
						errorZuKlient( "Du bist nicht eingeloggt." );
						break;
					case 1:
						errorZuKlient( "Du wurdest bereits einem Spiel zugeordnet." );
						break;
					case 2:
						errorZuKlient( "Du bist in einem anderen noch laufendem Spiel. Spiele es zu Ende." );
						break;
					case 3:
						errorZuKlient( "Du bist in einer anderen Gruppe." );
						break;
					case 4:
						errorZuKlient( "Du bist bereits in der Warteschlange." );
						break;
					case 5:
						errorZuKlient( "Die Karte ist zur Zeit nicht spielbar." );
						break;
					case 6:
						errorZuKlient( "Unbekannter Fehler." );
						break;
					case 7:
						klient->sendeEncrypted( "\1", 1 );
						break;
					}
				}
				break;
			case 0xF: // spieler abmelden
				if( !klientNummer )
				{
					errorZuKlient( "Du bist nicht Identifiziert." );
					break;
				}
				klient->sendeEncrypted( "\1", 1 );
				as->zDB()->accountAbmelden( accountId );
				break;
			case 0x10: // gruppe Spiel Starten
				if( 1 )
				{
					if( !klientNummer )
					{
						errorZuKlient( "Du bist nicht Identifiziert." );
						break;
					}
					klient->sendeEncrypted( "\1", 1 );
					char spielStarten = 0;
					int gruppeId = 0;
					klient->getNachrichtEncrypted( (char*)&gruppeId, 4 );
					klient->getNachrichtEncrypted( &spielStarten, 1 );
					if( spielStarten && as->zDB()->getSpielerInGruppeAnzahl( gruppeId ) < 2 )
					{
						errorZuKlient( "Es müssen sich mindestens 2 Spieler in der Gruppe befinden." );
						break;
					}
					if( as->zDB()->setGruppeSpielStarten( accountId, gruppeId, spielStarten == 1 ) )
					{
						klient->sendeEncrypted( "\1", 1 );
						MsgWeiterleitung *weiter = new MsgWeiterleitung( accountId, as->getThis() );
						weiter->gruppeSpielStarten( gruppeId, spielStarten == 1 );
						weiter->release();
					}
					else
						errorZuKlient( "Du kannst diese Option nicht setzen." );
				}
				break;
			case 0x11: // gruppe Einladung abbrechen
				if( 1 )
				{
					if( !klientNummer )
					{
						errorZuKlient( "Du bist nicht Identifiziert." );
						break;
					}
					klient->sendeEncrypted( "\1", 1 );
					int gruppeId = 0;
					int accountId = 0;
					klient->getNachrichtEncrypted( (char*)&gruppeId, 4 );
					klient->getNachrichtEncrypted( (char*)&accountId, 4 );
					if( as->zDB()->gruppeEinladungAbbrechen( this->accountId, gruppeId, accountId ) )
					{
						klient->sendeEncrypted( "\1", 1 );
						MsgWeiterleitung *weiter = new MsgWeiterleitung( accountId, as->getThis() );
						weiter->spielEinladungAbbrechen( gruppeId, accountId );
						weiter->release();
					}
					else
						errorZuKlient( "Du kannst diese Option nicht setzen." );
				}
				break;
			case 0x12: // gruppe Einladung ablehnen
				if( 1 )
				{
					if( !klientNummer )
					{
						errorZuKlient( "Du bist nicht Identifiziert." );
						break;
					}
					klient->sendeEncrypted( "\1", 1 );
					int gruppeId = 0;
					klient->getNachrichtEncrypted( (char*)&gruppeId, 4 );
					klient->sendeEncrypted( "\1", 1 );
					as->zDB()->gruppeEinladungAbbrechen( as->zDB()->getGruppeAdminId( gruppeId ), gruppeId, accountId );
					MsgWeiterleitung *weiter = new MsgWeiterleitung( accountId, as->getThis() );
					weiter->spielEinladungAblehnen( gruppeId );
					weiter->release();
				}
				break;
			case 0x13: // ping
				if( 1 )
				{
					if( !klientNummer )
					{
						errorZuKlient( "Du bist nicht Identifiziert." );
						break;
					}
					klient->sendeEncrypted( "\1", 1 );
				}
				break;
			default:
				errorZuKlient( "Unbekannte Nachricht!" );
				break;
			}
			if( br )
				break;
			as->addEmpfangen( klient->getDownloadBytes( 1 ) );
			as->addGesendet( klient->getUploadBytes( 1 ) );
		}
	}
	as->addEmpfangen( klient->getDownloadBytes( 1 ) );
	as->addGesendet( klient->getUploadBytes( 1 ) );
	as->removeKlient( this ); // delete this
}

// constant
void ASKlient::errorZuKlient( const char *nachricht ) const // sendet eine Fehlernachricht zum Klient
{
	klient->sendeEncrypted( "\3", 1 );
	char key = (char)textLength( nachricht );
	klient->sendeEncrypted( &key, 1 );
	klient->sendeEncrypted( nachricht, key );
}

int ASKlient::getKlientNummer() const // gibt die KlientId zurück
{
	return klientNummer;
}

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

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

// Inhalt der MsgWeiterleitung Klasse aus AnmeldungServer.h
// Konstruktor
MsgWeiterleitung::MsgWeiterleitung( int accountId, AnmeldungServer *as )
{
	fehler = new Text( "" );
	this->accountId = accountId;
	this->as = as;
	ref = 1;
}

// Destruktor
MsgWeiterleitung::~MsgWeiterleitung()
{
	fehler->release();
	as->release();
}

// nicht constant
bool MsgWeiterleitung::spielerBetrittGruppe( int gruppeId )
{
	bool ret = 1;
	Array< int > *accId = new Array< int >();
	int anzahl = 0;
	as->zDB()->getSpielerInGruppe( gruppeId, accId, &anzahl );
	for( int i = 0; i < anzahl; i++ )
	{
		int account = accId->get( i );
		if( account == accountId )
			continue;
		Text *ip = new Text( "" );
		int port = 0;
		ret = ret & as->zDB()->getChatServer( account, ip, &port );
		if( ip->istGleich( as->getIp() ) )
			ip->setText( "127.0.0.1" );
		if( ip->getLength() )
		{
			Klient *klient = new Klient();
			unsigned char key[ 20 ] = { 78, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
			klient->setSendeKey( (char*)key, 20 );
			klient->setEmpfangKey( (char*)key, 20 );
			ret = ret & klient->verbinde( (unsigned short)port, ip->getText() );
			ret = ret & klient->sendeEncrypted( "\5\x14", 2 );
			char res = 0;
			ret = ret & klient->getNachrichtEncrypted( &res, 1 );
			if( res )
			{
				ret = ret & klient->sendeEncrypted( (char*)&account, 4 );
				ret = ret & klient->sendeEncrypted( (char*)&accountId, 4 );
				ret = ret & klient->sendeEncrypted( (char*)&gruppeId, 4 );
				ret = ret & klient->getNachrichtEncrypted( &res, 1 );
			}
			ret = (char)ret & res;
			as->addEmpfangen( klient->getDownloadBytes( 1 ) );
			as->addGesendet( klient->getUploadBytes( 1 ) );
			klient->trenne();
			klient = klient->release();
		}
		ip->release();
	}
	accId->release();
	if( !ret )
		fehler->setText( "Einer oder mehr Accounts konnen nicht erreicht werden" );
	return ret;
}

bool MsgWeiterleitung::spielerLeavesGruppe( int gruppeId )
{
	bool ret = 1;
	Array< int > *accId = new Array< int >();
	int anzahl = 0;
	as->zDB()->getSpielerInGruppe( gruppeId, accId, &anzahl );
	for( int i = 0; i < anzahl; i++ )
	{
		int account = accId->get( i );
		if( account == accountId )
			continue;
		Text *ip = new Text( "" );
		int port = 0;
		ret = ret & as->zDB()->getChatServer( account, ip, &port );
		if( ip->istGleich( as->getIp() ) )
			ip->setText( "127.0.0.1" );
		if( ip->getLength() )
		{
			Klient *klient = new Klient();
			unsigned char key[ 20 ] = { 78, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
			klient->setSendeKey( (char*)key, 20 );
			klient->setEmpfangKey( (char*)key, 20 );
			ret = ret & klient->verbinde( (unsigned short)port, ip->getText() );
			ret = ret & klient->sendeEncrypted( "\5\x15", 2 );
			char res = 0;
			ret = ret & klient->getNachrichtEncrypted( &res, 1 );
			if( res )
			{
				ret = ret & klient->sendeEncrypted( (char*)&account, 4 );
				ret = ret & klient->sendeEncrypted( (char*)&accountId, 4 );
				ret = ret & klient->sendeEncrypted( (char*)&gruppeId, 4 );
				ret = ret & klient->getNachrichtEncrypted( &res, 1 );
			}
			ret = (char)ret & res;
			as->addEmpfangen( klient->getDownloadBytes( 1 ) );
			as->addGesendet( klient->getUploadBytes( 1 ) );
			klient->trenne();
			klient = klient->release();
		}
		ip->release();
	}
	accId->release();
	if( !ret )
		fehler->setText( "Einer oder mehr Accounts konnen nicht erreicht werden" );
	return ret;
}

bool MsgWeiterleitung::setGruppeAdmin( int gruppeId, int admin )
{
	bool ret = 1;
	Array< int > *accId = new Array< int >();
	int anzahl = 0;
	as->zDB()->getSpielerInGruppe( gruppeId, accId, &anzahl );
	for( int i = 0; i < anzahl; i++ )
	{
		int account = accId->get( i );
		if( account == accountId )
			continue;
		Text *ip = new Text( "" );
		int port = 0;
		ret = ret & as->zDB()->getChatServer( account, ip, &port );
		if( ip->istGleich( as->getIp() ) )
			ip->setText( "127.0.0.1" );
		if( ip->getLength() )
		{
			Klient *klient = new Klient();
			unsigned char key[ 20 ] = { 78, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
			klient->setSendeKey( (char*)key, 20 );
			klient->setEmpfangKey( (char*)key, 20 );
			ret = ret & klient->verbinde( (unsigned short)port, ip->getText() );
			ret = ret & klient->sendeEncrypted( "\5\x1B", 2 );
			char res = 0;
			ret = ret & klient->getNachrichtEncrypted( &res, 1 );
			if( res )
			{
				ret = ret & klient->sendeEncrypted( (char*)&account, 4 );
				ret = ret & klient->sendeEncrypted( (char*)&admin, 4 );
				ret = ret & klient->sendeEncrypted( (char*)&gruppeId, 4 );
				ret = ret & klient->getNachrichtEncrypted( &res, 1 );
			}
			ret = (char)ret & res;
			as->addEmpfangen( klient->getDownloadBytes( 1 ) );
			as->addGesendet( klient->getUploadBytes( 1 ) );
			klient->trenne();
			klient = klient->release();
		}
		ip->release();
	}
	accId->release();
	if( !ret )
		fehler->setText( "Einer oder mehr Accounts konnen nicht erreicht werden" );
	return ret;
}

bool MsgWeiterleitung::kickSpielerAusGruppe( int accountId, int gruppeId )
{
	bool ret = 1;
	Text *ip = new Text( "" );
	int port = 0;
	ret = ret & as->zDB()->getChatServer( accountId, ip, &port );
	if( ip->istGleich( as->getIp() ) )
		ip->setText( "127.0.0.1" );
	if( ip->getLength() )
	{
		Klient *klient = new Klient();
		unsigned char key[ 20 ] = { 78, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
		klient->setSendeKey( (char*)key, 20 );
		klient->setEmpfangKey( (char*)key, 20 );
		ret = ret & klient->verbinde( (unsigned short)port, ip->getText() );
		ret = ret & klient->sendeEncrypted( "\5\x16", 2 );
		char res = 0;
		ret = ret & klient->getNachrichtEncrypted( &res, 1 );
		if( res )
		{
			ret = ret & klient->sendeEncrypted( (char*)&accountId, 4 );
			ret = ret & klient->sendeEncrypted( (char*)&gruppeId, 4 );
			ret = ret & klient->getNachrichtEncrypted( &res, 1 );
		}
		ret = (char)ret & res;
		as->addEmpfangen( klient->getDownloadBytes( 1 ) );
		as->addGesendet( klient->getUploadBytes( 1 ) );
		klient->trenne();
		klient = klient->release();
	}
	ip->release();
	if( !ret )
		fehler->setText( "Einer oder mehr Accounts konnen nicht erreicht werden" );
	return ret;
}

bool MsgWeiterleitung::gruppenNachricht( int gruppeId, char *txt )
{
	bool ret = 1;
	char len = (char)textLength( txt );
	if( !len )
		return 0;
	Array< int > *accId = new Array< int >();
	int anzahl = 0;
	as->zDB()->getSpielerInGruppe( gruppeId, accId, &anzahl );
	for( int i = 0; i < anzahl; i++ )
	{
		int account = accId->get( i );
		Text *ip = new Text( "" );
		int port = 0;
		ret = ret & as->zDB()->getChatServer( account, ip, &port );
		if( ip->istGleich( as->getIp() ) )
			ip->setText( "127.0.0.1" );
		if( ip->getLength() )
		{
			Klient *klient = new Klient();
			unsigned char key[ 20 ] = { 78, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
			klient->setSendeKey( (char*)key, 20 );
			klient->setEmpfangKey( (char*)key, 20 );
			ret = ret & klient->verbinde( (unsigned short)port, ip->getText() );
			ret = ret & klient->sendeEncrypted( "\5\x19", 2 );
			char res = 0;
			ret = ret & klient->getNachrichtEncrypted( &res, 1 );
			if( res )
			{
				ret = ret & klient->sendeEncrypted( (char*)&account, 4 );
				ret = ret & klient->sendeEncrypted( (char*)&gruppeId, 4 );
				ret = ret & klient->sendeEncrypted( (char*)&len, 1 );
				if( len )
					ret = ret & klient->sendeEncrypted( txt, len );
				ret = ret & klient->getNachrichtEncrypted( &res, 1 );
			}
			ret = (char)ret & res;
			as->addEmpfangen( klient->getDownloadBytes( 1 ) );
			as->addGesendet( klient->getUploadBytes( 1 ) );
			klient->trenne();
			klient = klient->release();
		}
		ip->release();
	}
	accId->release();
	if( !ret )
		fehler->setText( "Einer oder mehr Accounts konnen nicht erreicht werden" );
	return ret;
}

bool MsgWeiterleitung::gruppeAngemeldet( int gruppeId )
{
	bool ret = 1;
	Array< int > *accId = new Array< int >();
	int anzahl = 0;
	as->zDB()->getSpielerInGruppe( gruppeId, accId, &anzahl );
	for( int i = 0; i < anzahl; i++ )
	{
		int account = accId->get( i );
		Text *ip = new Text( "" );
		int port = 0;
		ret = ret & as->zDB()->getChatServer( account, ip, &port );
		if( ip->istGleich( as->getIp() ) )
			ip->setText( "127.0.0.1" );
		if( ip->getLength() )
		{
			Klient *klient = new Klient();
			unsigned char key[ 20 ] = { 78, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
			klient->setSendeKey( (char*)key, 20 );
			klient->setEmpfangKey( (char*)key, 20 );
			ret = ret & klient->verbinde( (unsigned short)port, ip->getText() );
			ret = ret & klient->sendeEncrypted( "\5\x17", 2 );
			char res = 0;
			ret = ret & klient->getNachrichtEncrypted( &res, 1 );
			if( res )
			{
				ret = ret & klient->sendeEncrypted( (char*)&account, 4 );
				ret = ret & klient->sendeEncrypted( (char*)&gruppeId, 4 );
				ret = ret & klient->getNachrichtEncrypted( &res, 1 );
			}
			ret = (char)ret & res;
			as->addEmpfangen( klient->getDownloadBytes( 1 ) );
			as->addGesendet( klient->getUploadBytes( 1 ) );
			klient->trenne();
			klient = klient->release();
		}
		ip->release();
	}
	accId->release();
	if( !ret )
		fehler->setText( "Einer oder mehr Accounts konnen nicht erreicht werden" );
	return ret;
}

bool MsgWeiterleitung::gruppeAbgemeldet( int gruppeId )
{
	bool ret = 1;
	Array< int > *accId = new Array< int >();
	int anzahl = 0;
	as->zDB()->getSpielerInGruppe( gruppeId, accId, &anzahl );
	for( int i = 0; i < anzahl; i++ )
	{
		int account = accId->get( i );
		Text *ip = new Text( "" );
		int port = 0;
		ret = ret & as->zDB()->getChatServer( account, ip, &port );
		if( ip->istGleich( as->getIp() ) )
			ip->setText( "127.0.0.1" );
		if( ip->getLength() )
		{
			Klient *klient = new Klient();
			unsigned char key[ 20 ] = { 78, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
			klient->setSendeKey( (char*)key, 20 );
			klient->setEmpfangKey( (char*)key, 20 );
			ret = ret & klient->verbinde( (unsigned short)port, ip->getText() );
			ret = ret & klient->sendeEncrypted( "\5\x18", 2 );
			char res = 0;
			ret = ret & klient->getNachrichtEncrypted( &res, 1 );
			if( res )
			{
				ret = ret & klient->sendeEncrypted( (char*)&account, 4 );
				ret = ret & klient->sendeEncrypted( (char*)&gruppeId, 4 );
				ret = ret & klient->getNachrichtEncrypted( &res, 1 );
			}
			ret = (char)ret & res;
			as->addEmpfangen( klient->getDownloadBytes( 1 ) );
			as->addGesendet( klient->getUploadBytes( 1 ) );
			klient->trenne();
			klient = klient->release();
		}
		ip->release();
	}
	accId->release();
	if( !ret )
		fehler->setText( "Einer oder mehr Accounts konnen nicht erreicht werden" );
	return ret;
}

bool MsgWeiterleitung::gruppeSpielStarten( int gruppeId, bool starten )
{
	bool ret = 1;
	Array< int > *accId = new Array< int >();
	int anzahl = 0;
	as->zDB()->getSpielerInGruppe( gruppeId, accId, &anzahl );
	for( int i = 0; i < anzahl; i++ )
	{
		int account = accId->get( i );
		Text *ip = new Text( "" );
		int port = 0;
		ret = ret & as->zDB()->getChatServer( account, ip, &port );
		if( ip->istGleich( as->getIp() ) )
			ip->setText( "127.0.0.1" );
		if( ip->getLength() )
		{
			Klient *klient = new Klient();
			unsigned char key[ 20 ] = { 78, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
			klient->setSendeKey( (char*)key, 20 );
			klient->setEmpfangKey( (char*)key, 20 );
			ret = ret & klient->verbinde( (unsigned short)port, ip->getText() );
			ret = ret & klient->sendeEncrypted( "\5\x1A", 2 );
			char res = 0;
			ret = ret & klient->getNachrichtEncrypted( &res, 1 );
			if( res )
			{
				ret = ret & klient->sendeEncrypted( (char*)&account, 4 );
				ret = ret & klient->sendeEncrypted( (char*)&gruppeId, 4 );
				ret = ret & klient->sendeEncrypted( (char*)&starten, 1 );
				ret = ret & klient->getNachrichtEncrypted( &res, 1 );
			}
			ret = (char)ret & res;
			as->addEmpfangen( klient->getDownloadBytes( 1 ) );
			as->addGesendet( klient->getUploadBytes( 1 ) );
			klient->trenne();
			klient = klient->release();
		}
		ip->release();
	}
	accId->release();
	if( !ret )
		fehler->setText( "Einer oder mehr Accounts konnen nicht erreicht werden" );
	return ret;
}

bool MsgWeiterleitung::spielEinladung( int gruppeId, int accountId )
{
	// Einladung zum spieler Senden
	bool ret = 1;
	Text *ip = new Text( "" );
	int port = 0;
	ret = ret & as->zDB()->getChatServer( accountId, ip, &port );
	if( ip->istGleich( as->getIp() ) )
		ip->setText( "127.0.0.1" );
	if( ip->getLength() )
	{
		Klient *klient = new Klient();
		unsigned char key[ 20 ] = { 78, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
		klient->setSendeKey( (char*)key, 20 );
		klient->setEmpfangKey( (char*)key, 20 );
		ret = ret & klient->verbinde( (unsigned short)port, ip->getText() );
		ret = ret & klient->sendeEncrypted( "\5\5", 2 );
		char res = 0;
		ret = ret & klient->getNachrichtEncrypted( &res, 1 );
		if( res )
		{
			ret = ret & klient->sendeEncrypted( (char*)&accountId, 4 );
			ret = ret & klient->sendeEncrypted( (char*)&this->accountId, 4 );
			ret = ret & klient->sendeEncrypted( (char*)&gruppeId, 4 );
			ret = ret & klient->getNachrichtEncrypted( &res, 1 );
		}
		ret = (char)ret & res;
		as->addEmpfangen( klient->getDownloadBytes( 1 ) );
		as->addGesendet( klient->getUploadBytes( 1 ) );
		klient->trenne();
		klient = klient->release();
	}
	ip->release();
	// Einladung zu den Gruppenmitgliedern senden
	Array< int > *accId = new Array< int >();
	int anzahl = 0;
	as->zDB()->getSpielerInGruppe( gruppeId, accId, &anzahl );
	for( int i = 0; i < anzahl; i++ )
	{
		int account = accId->get( i );
		Text *ip = new Text( "" );
		int port = 0;
		ret = ret & as->zDB()->getChatServer( account, ip, &port );
		if( ip->istGleich( as->getIp() ) )
			ip->setText( "127.0.0.1" );
		if( ip->getLength() )
		{
			Klient *klient = new Klient();
			unsigned char key[ 20 ] = { 78, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
			klient->setSendeKey( (char*)key, 20 );
			klient->setEmpfangKey( (char*)key, 20 );
			ret = ret & klient->verbinde( (unsigned short)port, ip->getText() );
			ret = ret & klient->sendeEncrypted( "\5\x1F", 2 );
			char res = 0;
			ret = ret & klient->getNachrichtEncrypted( &res, 1 );
			if( res )
			{
				ret = ret & klient->sendeEncrypted( (char*)&account, 4 );
				ret = ret & klient->sendeEncrypted( (char*)&gruppeId, 4 );
				ret = ret & klient->sendeEncrypted( (char*)&accountId, 4 );
				ret = ret & klient->getNachrichtEncrypted( &res, 1 );
			}
			ret = (char)ret & res;
			as->addEmpfangen( klient->getDownloadBytes( 1 ) );
			as->addGesendet( klient->getUploadBytes( 1 ) );
			klient->trenne();
			klient = klient->release();
		}
		ip->release();
	}
	accId->release();
	if( !ret )
		fehler->setText( "Einer oder mehr Accounts konnen nicht erreicht werden" );
	return ret;
}

bool MsgWeiterleitung::spielEinladungAbbrechen( int gruppeId, int accountId )
{
	bool ret = 1;
	Array< int > *accId = new Array< int >();
	int anzahl = 0;
	as->zDB()->getSpielerInGruppe( gruppeId, accId, &anzahl );
	for( int i = 0; i < anzahl; i++ )
	{
		int account = accId->get( i );
		Text *ip = new Text( "" );
		int port = 0;
		ret = ret & as->zDB()->getChatServer( account, ip, &port );
		if( ip->istGleich( as->getIp() ) )
			ip->setText( "127.0.0.1" );
		if( ip->getLength() )
		{
			Klient *klient = new Klient();
			unsigned char key[ 20 ] = { 78, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
			klient->setSendeKey( (char*)key, 20 );
			klient->setEmpfangKey( (char*)key, 20 );
			ret = ret & klient->verbinde( (unsigned short)port, ip->getText() );
			ret = ret & klient->sendeEncrypted( "\5\x1E", 2 );
			char res = 0;
			ret = ret & klient->getNachrichtEncrypted( &res, 1 );
			if( res )
			{
				ret = ret & klient->sendeEncrypted( (char*)&account, 4 );
				ret = ret & klient->sendeEncrypted( (char*)&gruppeId, 4 );
				ret = ret & klient->sendeEncrypted( (char*)&accountId, 4 );
				ret = ret & klient->getNachrichtEncrypted( &res, 1 );
			}
			ret = (char)ret & res;
			as->addEmpfangen( klient->getDownloadBytes( 1 ) );
			as->addGesendet( klient->getUploadBytes( 1 ) );
			klient->trenne();
			klient = klient->release();
		}
		ip->release();
	}
	accId->release();
	if( !ret )
		fehler->setText( "Einer oder mehr Accounts konnen nicht erreicht werden" );
	return ret;
}

bool MsgWeiterleitung::spielEinladungAblehnen( int gruppeId )
{
	bool ret = 1;
	Array< int > *accId = new Array< int >();
	int anzahl = 0;
	as->zDB()->getSpielerInGruppe( gruppeId, accId, &anzahl );
	for( int i = 0; i < anzahl; i++ )
	{
		int account = accId->get( i );
		Text *ip = new Text( "" );
		int port = 0;
		ret = ret & as->zDB()->getChatServer( account, ip, &port );
		if( ip->istGleich( as->getIp() ) )
			ip->setText( "127.0.0.1" );
		if( ip->getLength() )
		{
			Klient *klient = new Klient();
			unsigned char key[ 20 ] = { 78, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
			klient->setSendeKey( (char*)key, 20 );
			klient->setEmpfangKey( (char*)key, 20 );
			ret = ret & klient->verbinde( (unsigned short)port, ip->getText() );
			ret = ret & klient->sendeEncrypted( "\5\x1C", 2 );
			char res = 0;
			ret = ret & klient->getNachrichtEncrypted( &res, 1 );
			if( res )
			{
				ret = ret & klient->sendeEncrypted( (char*)&account, 4 );
				ret = ret & klient->sendeEncrypted( (char*)&accountId, 4 );
				ret = ret & klient->sendeEncrypted( (char*)&gruppeId, 4 );
				ret = ret & klient->getNachrichtEncrypted( &res, 1 );
			}
			ret = (char)ret & res;
			as->addEmpfangen( klient->getDownloadBytes( 1 ) );
			as->addGesendet( klient->getUploadBytes( 1 ) );
			klient->trenne();
			klient = klient->release();
		}
		ip->release();
	}
	accId->release();
	if( !ret )
		fehler->setText( "Einer oder mehr Accounts konnen nicht erreicht werden" );
	return ret;
}

// constant
int MsgWeiterleitung::getAccountId() const
{
	return accountId;
}

Text *MsgWeiterleitung::getLetzterFehler() const
{
	return fehler->getThis();
}

Text *MsgWeiterleitung::zLetzterFehler() const
{
	return fehler;
}

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

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