#include "../KSGKlient.h"
#include "../KSGServer.h"
#include "../../Global/Variablen.h"
#include "../Keys.h"

// Inhalt der ChatKlient Klasse aus KSGKlient.h
// Konstruktor
ChatKlient::ChatKlient()
{
    verbunden = 0;
    senden = 0;
    empfangen = 0;
    fehler = new Text( "" );
    klientId = getKlientId();
    ref = 1;
}

// Destruktor 
ChatKlient::~ChatKlient()
{
    cs.lock();
    if( senden )
    {
        char serverReturn = 0;
        if( verbunden )
        {
            senden->sendeEncrypted( "\4", 1 );
            senden->getNachrichtEncrypted( &serverReturn, 1 );
            senden->sendeEncrypted( "\3", 1 );
            senden->getNachrichtEncrypted( &serverReturn, 1 );
            senden->trenne();
        }
        senden = senden->release();
        verbunden = 0;
        if( empfangen )
        {
            warteAufThread( 5000 );
            ende();
            empfangen->trenne();
            empfangen = empfangen->release();
        }
    }
    fehler = fehler->release();
    cs.unlock();
}

// nicht constant
bool ChatKlient::verbinde() // verbindet ich mit dem Chat Server
{
    cs.lock();
    if( verbunden )
    {
        cs.unlock();
        return 1;
    }
    if( !senden )
    {
        char *msIp = getMainServerIp();
        unsigned short msPort = getMainServerPort();
        senden = new Klient();
        int keyLen = 0;
        char *key = 0;
        Keys::getServerKey( &key, keyLen, Keys::MAIN, Keys::SENDEN );
        senden->setSendeKey( key, keyLen );
        delete[] key;
        Keys::getServerKey( &key, keyLen, Keys::MAIN, Keys::EMPFANGEN );
        senden->setEmpfangKey( key, keyLen );
        delete[] key;
        if( !senden->verbinde( msPort, msIp ) )
        {
            fehler->setText( "Fehler beim verbinden mit dem Main Server. Bitte versuche es Sp�ter erneut." );
            senden = senden->release();
            delete[]msIp;
            cs.unlock();
            return 0;
        }
        delete[]msIp;
        senden->sende( "\0", 1 ); // Verschl�sselung aktivieren
        senden->sendeEncrypted( "\1", 1 );
        senden->sendeEncrypted( (char*)&klientId, 4 );
        char serverReturn = 0;
        senden->getNachrichtEncrypted( &serverReturn, 1 );
        if( serverReturn == 3 )
        {
            char l�n = 0;
            senden->getNachrichtEncrypted( &l�n, 1 );
            char *nachricht = new char[ l�n + 1 ];
            nachricht[ l�n ] = 0;
            senden->getNachrichtEncrypted( nachricht, l�n );
            fehler->setText( nachricht );
            delete[]nachricht;
            senden->sendeEncrypted( "\3", 1 );
            senden->getNachrichtEncrypted( &serverReturn, 1 );
            senden->trenne();
            senden = senden->release();
            cs.unlock();
            return 0;
        }
        char *sl = 0;
        char slL�n = getSchl�ssel( &sl );
        senden->setSendeKey( sl, slL�n );
        senden->setEmpfangKey( sl, slL�n );
        delete[] sl;
        senden->sendeEncrypted( "\6\5", 2 );
        char byte = 0;
        senden->getNachrichtEncrypted( &byte, 1 );
        if( byte == 2 )
        {
            unsigned char lsIp[ 4 ];
            senden->getNachrichtEncrypted( (char *)lsIp, 4 );
            unsigned short lsPort = 0;
            senden->getNachrichtEncrypted( (char*)&lsPort, 2 );
            senden->sendeEncrypted( "\3", 1 );
            senden->getNachrichtEncrypted( &serverReturn, 1 );
            senden->trenne();
            Text *lsIpT = new Text( "" );
            lsIpT->append( (int)lsIp[ 0 ] );
            lsIpT->append( "." );
            lsIpT->append( (int)lsIp[ 1 ] );
            lsIpT->append( "." );
            lsIpT->append( (int)lsIp[ 2 ] );
            lsIpT->append( "." );
            lsIpT->append( (int)lsIp[ 3 ] );
            int keyLen = 0;
            char *key = 0;
            Keys::getServerKey( &key, keyLen, Keys::CHAT, Keys::SENDEN );
            senden->setSendeKey( key, keyLen );
            delete[] key;
            Keys::getServerKey( &key, keyLen, Keys::CHAT, Keys::EMPFANGEN );
            senden->setEmpfangKey( key, keyLen );
            delete[] key;
            senden->verbinde( lsPort, lsIpT->getText() );
            lsIpT = lsIpT->release();
            //senden->sendeEncrypted( "\xFF", 1 );
            senden->sendeEncrypted( "\3", 1 );
            senden->getNachrichtEncrypted( &serverReturn, 1 );
            senden->trenne();
        }
        if( byte == 3 )
        {
            senden->getNachrichtEncrypted( &byte, 1 );
            char *f = new char[ byte + 1 ];
            f[ byte ] = 0;
            senden->getNachrichtEncrypted( f, byte );
            fehler->setText( f );
            delete[]f;
            senden->sendeEncrypted( "\3", 1 );
            senden->getNachrichtEncrypted( &serverReturn, 1 );
            senden->trenne();
            senden = senden->release();
            cs.unlock();
            return 0;
        }
    }
    int keyLen = 0;
    char *key = 0;
    Keys::getServerKey( &key, keyLen, Keys::CHAT, Keys::SENDEN );
    senden->setSendeKey( key, keyLen );
    delete[] key;
    Keys::getServerKey( &key, keyLen, Keys::CHAT, Keys::EMPFANGEN );
    senden->setEmpfangKey( key, keyLen );
    delete[] key;
    if( senden->verbinde( senden->getServerPort(), senden->getServerIp() ) )
    {
        if( senden->sendeEncrypted( "\1", 1 ) )
        {
            senden->sendeEncrypted( (char*)&klientId, 4 );
            char ret = 0;
            senden->getNachrichtEncrypted( &ret, 1 );
            if( ret != 1 )
            {
                char byte = 0;
                senden->getNachrichtEncrypted( &byte, 1 );
                char *f = new char[ byte + 1 ];
                f[ byte ] = 0;
                senden->getNachrichtEncrypted( f, byte );
                fehler->setText( f );
                delete[]f;
                senden->sendeEncrypted( "\3", 1 );
                char serverReturn = 0;
                senden->getNachrichtEncrypted( &serverReturn, 1 );
                senden->trenne();
                cs.unlock();
                return 0;
            }
            char *sl = 0;
            char slL�n = getSchl�ssel( &sl );
            senden->setSendeKey( sl, slL�n );
            senden->setEmpfangKey( sl, slL�n );
            delete[] sl;
            if( !empfangen )
                empfangen = new Klient();
            int keyLen = 0;
            char *key = 0;
            Keys::getServerKey( &key, keyLen, Keys::CHAT, Keys::SENDEN );
            empfangen->setSendeKey( key, keyLen );
            delete[] key;
            Keys::getServerKey( &key, keyLen, Keys::CHAT, Keys::EMPFANGEN );
            empfangen->setEmpfangKey( key, keyLen );
            delete[] key;
            if( empfangen->verbinde( senden->getServerPort(), senden->getServerIp() ) )
            {
                start();
                verbunden = 1;
                cs.unlock();
                return 1;
            }
            else
            {
                fehler->setText( "Der dir zugewiesene Chat Server kann dir keine Nachrichten senden." );
                cs.unlock();
                return 1;
            }
        }
        else
        {
            fehler->setText( "Der dir zugewiesene Chat Server hat die Verbindung abgebrochen. Bitte versuche es Sp�ter erneut." );
            senden = senden->release();
        }
    }
    else
    {
        fehler->setText( "Der dir zugewiesene Chat Server antwortet nicht. Bitte versuche es Sp�ter erneut." );
        senden = senden->release();
    }
    cs.unlock();
    return 0;
}

bool ChatKlient::chatNachricht( int zuAccount, const char *nachricht ) // sendet eine Nachricht zu einem Account
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    char l�n = textLength( nachricht );
    if( !l�n )
        return 1;
    cs.lock();
    senden->sendeEncrypted( "\6", 1 );
    char serverReturn = 0;
    senden->getNachrichtEncrypted( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeEncrypted( (char*)&zuAccount, 4 );
        senden->sendeEncrypted( &l�n, 1 );
        senden->sendeEncrypted( nachricht, l�n );
    }
    else
    {
        cs.unlock();
        return 0;
    }
    cs.unlock();
    return 1;
}

bool ChatKlient::accountName�ndern( const char *name ) // �ndert den Account Namen
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    char l�n = textLength( name );
    if( !l�n )
        return 1;
    cs.lock();
    senden->sendeEncrypted( "\x8", 1 );
    char serverReturn = 0;
    senden->getNachrichtEncrypted( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeEncrypted( &l�n, 1 );
        senden->sendeEncrypted( name, l�n );
        senden->getNachrichtEncrypted( &serverReturn, 1 );
        cs.unlock();
        return serverReturn == 1;
    }
    else
    {
        cs.unlock();
        return 0;
    }
}

bool ChatKlient::freundschaftBeenden( int accountId ) // beendet die Freundschaft mit einem Account
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    cs.lock();
    senden->sendeEncrypted( "\x9", 1 );
    char serverReturn = 0;
    senden->getNachrichtEncrypted( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeEncrypted( (char*)&accountId, 4 );
        senden->getNachrichtEncrypted( &serverReturn, 1 );
        cs.unlock();
        return serverReturn == 1;
    }
    else
    {
        cs.unlock();
        return 0;
    }
}

bool ChatKlient::freundesAnfrage( int accountId ) // sendet eine Freundesanfragezu einem Account
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    cs.lock();
    senden->sendeEncrypted( "\xA", 1 );
    char serverReturn = 0;
    senden->getNachrichtEncrypted( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeEncrypted( (char*)&accountId, 4 );
        senden->getNachrichtEncrypted( &serverReturn, 1 );
        cs.unlock();
        return serverReturn == 1;
    }
    else
    {
        cs.unlock();
        return 0;
    }
}

bool ChatKlient::freundesAnfrageBeantworten( int accountId, bool ja ) // beantwortet eine Freundesanfrage
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    cs.lock();
    senden->sendeEncrypted( "\xB", 1 );
    char serverReturn = 0;
    senden->getNachrichtEncrypted( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeEncrypted( (char*)&accountId, 4 );
        char ok = (char)ja;
        senden->sendeEncrypted( &ok, 1 );
        senden->getNachrichtEncrypted( &serverReturn, 1 );
        cs.unlock();
        return serverReturn == 1;
    }
    else
    {
        cs.unlock();
        return 0;
    }
}

int ChatKlient::chatroomErstellen( const char *name ) // erstellt ein chatroom
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    char l�n = textLength( name );
    if( !l�n )
        return 0;
    cs.lock();
    senden->sendeEncrypted( "\xC", 1 );
    char serverReturn = 0;
    senden->getNachrichtEncrypted( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeEncrypted( &l�n, 1 );
        senden->sendeEncrypted( name, l�n );
        senden->getNachrichtEncrypted( &serverReturn, 1 );
        if( !serverReturn )
        {
            cs.unlock();
            return 0;
        }
        int ret = 0;
        senden->getNachrichtEncrypted( (char*)&ret, 4 );
        cs.unlock();
        return ret;
    }
    else
    {
        cs.unlock();
        return 0;
    }
}

bool ChatKlient::chatroomEinladung( int accountId, int chatroomId ) // verschickt eine Einladung zu einem Chatroom
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    cs.lock();
    senden->sendeEncrypted( "\xD", 1 );
    char serverReturn = 0;
    senden->getNachrichtEncrypted( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeEncrypted( (char*)&accountId, 4 );
        senden->sendeEncrypted( (char*)&chatroomId, 4 );
        senden->getNachrichtEncrypted( &serverReturn, 1 );
        cs.unlock();
        return serverReturn == 1;
    }
    else
    {
        cs.unlock();
        return 0;
    }
}

bool ChatKlient::chatroomEinladungAblehnen( int accountId, int chatroomId ) // Einladung zum Chatroom wird abgelehnt
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    cs.lock();
    senden->sendeEncrypted( "\xE", 1 );
    char serverReturn = 0;
    senden->getNachrichtEncrypted( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeEncrypted( (char*)&accountId, 4 );
        senden->sendeEncrypted( (char*)&chatroomId, 4 );
        senden->getNachrichtEncrypted( &serverReturn, 1 );
        cs.unlock();
        return serverReturn == 1;
    }
    else
    {
        cs.unlock();
        return 0;
    }
}

bool ChatKlient::chatroomBetreten( int chatroomId ) // betritt ein chatroom
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    cs.lock();
    senden->sendeEncrypted( "\xF", 1 );
    char serverReturn = 0;
    senden->getNachrichtEncrypted( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeEncrypted( (char*)&chatroomId, 4 );
        senden->getNachrichtEncrypted( &serverReturn, 1 );
        cs.unlock();
        return serverReturn == 1;
    }
    else
    {
        cs.unlock();
        return 0;
    }
}

bool ChatKlient::chatroomNachricht( int chatroomId, const char *nachricht ) // chatroom Nachricht senden
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    char l�n = textLength( nachricht );
    if( !l�n )
        return 0;
    cs.lock();
    senden->sendeEncrypted( "\x10", 1 );
    char serverReturn = 0;
    senden->getNachrichtEncrypted( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeEncrypted( (char*)&chatroomId, 4 );
        senden->sendeEncrypted( &l�n, 1 );
        senden->sendeEncrypted( nachricht, l�n );
        senden->getNachrichtEncrypted( &serverReturn, 1 );
        cs.unlock();
        return serverReturn == 1;
    }
    else
    {
        cs.unlock();
        return 0;
    }
}

bool ChatKlient::chatroomVerlassen( int chatroomId ) // verl�sst chatroom
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    cs.lock();
    senden->sendeEncrypted( "\x11", 1 );
    char serverReturn = 0;
    senden->getNachrichtEncrypted( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeEncrypted( (char*)&chatroomId, 4 );
        senden->getNachrichtEncrypted( &serverReturn, 1 );
        cs.unlock();
        return serverReturn == 1;
    }
    else
    {
        cs.unlock();
        return 0;
    }
}

bool ChatKlient::chatroomKick( int chatroomId, int accountId ) // kickt Spieler aus Chatroom( nur wenn admin )
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    cs.lock();
    senden->sendeEncrypted( "\x12", 1 );
    char serverReturn = 0;
    senden->getNachrichtEncrypted( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeEncrypted( (char*)&chatroomId, 4 );
        senden->sendeEncrypted( (char*)&accountId, 4 );
        senden->getNachrichtEncrypted( &serverReturn, 1 );
        cs.unlock();
        return serverReturn == 1;
    }
    else
    {
        cs.unlock();
        return 0;
    }
}

bool ChatKlient::freundesListeAnfragen() // fragt nach allen freunden
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    char serverReturn = 0;
    cs.lock();
    senden->sendeEncrypted( "\x13", 1 );
    senden->getNachrichtEncrypted( &serverReturn, 1 );
    cs.unlock();
    return serverReturn == 1;
}

bool ChatKlient::chatNachrichtAnfrage() // fragt nach chat nachrichten in abwesenheit
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    char serverReturn = 0;
    cs.lock();
    senden->sendeEncrypted( "\x14", 1 );
    senden->getNachrichtEncrypted( &serverReturn, 1 );
    cs.unlock();
    return serverReturn == 1;
}

bool ChatKlient::keepAlive() // Erh�lt die Verbindung aufrecht
{
    if( !verbunden )
        return 0;
    char res = 0;
    if( !cs.tryLock() )
        return 1;
    senden->sendeEncrypted( "\x15", 1 );
    senden->getNachrichtEncrypted( &res, 1 );
    cs.unlock();
    if( res != 1 )
        trenne();
    return res == 1;
}

bool ChatKlient::trenne() // trennt sich von dem Chat Server
{
    if( !verbunden )
        return 1;
    cs.lock();
    senden->sendeEncrypted( "\3", 1 );
    char serverReturn = 0;
    senden->getNachrichtEncrypted( &serverReturn, 1 );
    senden->trenne();
    verbunden = 0;
    warteAufThread( 5000 );
    ende();
    if( empfangen )
        empfangen->trenne();
    cs.unlock();
    return 1;
}

void ChatKlient::thread() // empfangen von Nachrichten
{
    if( !verbunden || !empfangen || !senden )
        return;
    empfangen->sendeEncrypted( "\1", 1 );
    empfangen->sendeEncrypted( (char*)&klientId, 4 );
    char res = 0;
    empfangen->getNachrichtEncrypted( &res, 1 );
    if( res == 3 )
    {
        char l�n = 0;
        senden->getNachrichtEncrypted( &l�n, 1 );
        char *nachricht = new char[ l�n + 1 ];
        nachricht[ l�n ] = 0;
        senden->getNachrichtEncrypted( nachricht, l�n );
        fehler->setText( nachricht );
        delete[]nachricht;
    }
    if( res != 1 )
    {
        WMessageBox( 0, new Text( "Fehler" ), new Text( "Server akzeptiert den Klient nicht" ), MB_ICONERROR );
        return;
    }
    char *sl = 0;
    char slL�n = getSchl�ssel( &sl );
    empfangen->setSendeKey( sl, slL�n );
    empfangen->setEmpfangKey( sl, slL�n );
    delete[] sl;
    char befehl = 0;
    while( verbunden )
    {
        if( !empfangen->getNachrichtEncrypted( &befehl, 1 ) )
            return;
        switch( befehl )
        {
        case 0: // verbindung getrennt
            return;
            break;
        case 1: // kick
            if( 1 )
            {
                loginKlient->trenne();
                infoKlient->trenne();
                chatKlient->trenne();
                aktion = 4;
            }
            break;
        case 2: // Server Ausgelastet
            aktion = 1;
            if( nachLogin && nachLogin->zNachrichtenListe() )
            {
                hauptScreen->lock();
                nachLogin->zNachrichtenListe()->addNachricht( new Text( "Server Ausgelastet" ),
                                                              new Text( "Der Chat Server ist derzeit ausgelastet. Es wird versucht auf einen anderen Server auszuweichen." ),
                                                              new Text( "Ok" ), 0, NachrichtType::nachricht, 0 );
                hauptScreen->unlock();
            }
            break;
        case 3: // Fehler
            if( 1 )
            {
                char l�nge = 0;
                empfangen->getNachrichtEncrypted( &l�nge, 1 );
                char *txt = new char[ l�nge + 1 ];
                txt[ l�nge ] = 0;
                empfangen->getNachrichtEncrypted( txt, l�nge );
                hauptScreen->lock();
                if( nachLogin && nachLogin->zNachrichtenListe() )
                    nachLogin->zNachrichtenListe()->addNachricht( new Text( "Fehler" ), new Text( txt ), new Text( "Ok" ), 0, NachrichtType::nachricht, 0 );
                hauptScreen->unlock();
                delete[]txt;
            }
            break;
        case 4: // Chat Nachricht
            if( 1 )
            {
                int vonAccount = 0;
                empfangen->getNachrichtEncrypted( (char*)&vonAccount, 4 );
                char l�nge = 0;
                empfangen->getNachrichtEncrypted( &l�nge, 1 );
                char *nachricht = new char[ l�nge + 1 ];
                nachricht[ l�nge ] = 0;
                empfangen->getNachrichtEncrypted( nachricht, l�nge );
                if( nachLogin && nachLogin->zChatLeiste() )
                {
                    hauptScreen->lock();
                    nachLogin->zChatLeiste()->chatNachricht( vonAccount, nachricht );
                    hauptScreen->unlock();
                }
                delete[]nachricht;
            }
            break;
        case 5: // Spiel Einladung
            if( 1 )
            {
                int vonAccount = 0;
                empfangen->getNachrichtEncrypted( (char*)&vonAccount, 4 );
                int gruppeId = 0;
                empfangen->getNachrichtEncrypted( (char*)&gruppeId, 4 );
                if( nachLogin && nachLogin->zNachrichtenListe() )
                {
                    int karteId = infoKlient->getGruppenKarteId( gruppeId );
                    int spielId = infoKlient->getSpielId( karteId );
                    Text *spiel = infoKlient->getSpielName( spielId );
                    Text *karte = infoKlient->getKarteName( karteId );
                    Text *name = infoKlient->getSpielerName( vonAccount );
                    Text *titel = new Text( "Spiel Einladung" );
                    Text *nachricht = new Text( "Von: " );
                    nachricht->append( name );
                    nachricht->append( "\nSpiel: " );
                    nachricht->append( spiel );
                    nachricht->append( "\nKarte: " );
                    nachricht->append( karte );
                    SpielEinladungParam *param = new SpielEinladungParam();
                    param->gruppeId = gruppeId;
                    param->vonAccount = vonAccount;
                    hauptScreen->lock();
                    nachLogin->zNachrichtenListe()->addNachricht( titel, nachricht, new Text( "annehmen" ), new Text( "ablehnen" ), NachrichtType::spielEinladung, param );
                    hauptScreen->unlock();
                }
            }
            break;
        case 6: // Account Status �ndert sich
            if( 1 )
            {
                int accountId = 0;
                empfangen->getNachrichtEncrypted( (char*)&accountId, 4 );
                char l�n = 0;
                empfangen->getNachrichtEncrypted( &l�n, 1 );
                char *status = new char[ l�n + 1 ];
                status[ l�n ] = 0;
                empfangen->getNachrichtEncrypted( status, l�n );
                hauptScreen->lock();
                if( nachLogin && nachLogin->zNachrichtenListe() )
                    nachLogin->zFreundesListe()->setStatus( accountId, status );
                hauptScreen->unlock();
                delete[]status;
            }
            break;
        case 7: // Account Name �ndert sich
            if( 1 )
            {
                int accountId = 0;
                empfangen->getNachrichtEncrypted( (char*)&accountId, 4 );
                char l�n = 0;
                empfangen->getNachrichtEncrypted( &l�n, 1 );
                char *name = new char[ l�n + 1 ];
                name[ l�n ] = 0;
                empfangen->getNachrichtEncrypted( name, l�n );
                hauptScreen->lock();
                if( nachLogin && nachLogin->zNachrichtenListe() )
                    nachLogin->zFreundesListe()->setName( accountId, name );
                hauptScreen->unlock();
                delete[]name;
            }
            break;
        case 8: // kein Freund mehr
            if( 1 )
            {
                int accountId = 0;
                empfangen->getNachrichtEncrypted( (char*)&accountId, 4 );
                hauptScreen->lock();
                if( nachLogin && nachLogin->zNachrichtenListe() )
                    nachLogin->zFreundesListe()->removeMember( accountId );
                hauptScreen->unlock();
            }
            break;
        case 9: // Freundesanfrage
            if( 1 )
            {
                int vonAccount = 0;
                empfangen->getNachrichtEncrypted( (char*)&vonAccount, 4 );
                if( nachLogin->zNachrichtenListe() )
                {
                    Text *titel = new Text( "Freundeseinladung" );
                    Text *nachricht = new Text( "" );
                    nachricht->append( infoKlient->getSpielerName( vonAccount ) );
                    nachricht->append( " m�chte sich mit dir befreunden." );
                    int *accountId = new int;
                    *accountId = vonAccount;
                    hauptScreen->lock();
                    if( nachLogin && nachLogin->zNachrichtenListe() )
                    {
                        nachLogin->zNachrichtenListe()->addNachricht( titel, nachricht, new Text( "annehmen" ), new Text( "ablehnen" ),
                                                                      NachrichtType::freundEinladung, (void*)accountId );
                    }
                    hauptScreen->unlock();
                }
            }
            break;
        case 0xA: // Neuer Freund
            if( 1 )
            {
                int accountId = 0;
                empfangen->getNachrichtEncrypted( (char*)&accountId, 4 );
                hauptScreen->lock();
                if( nachLogin && nachLogin->zNachrichtenListe() )
                    nachLogin->zFreundesListe()->addMember( accountId );
                hauptScreen->unlock();
            }
            break;
        case 0xB: // Freundesanfrage abgelehnt
            if( 1 )
            {
                int vonAccount = 0;
                empfangen->getNachrichtEncrypted( (char*)&vonAccount, 4 );
                if( nachLogin && nachLogin->zNachrichtenListe() )
                {
                    Text *titel = new Text( "Freundeseinladung Abgelehnt" );
                    Text *nachricht = new Text( "" );
                    nachricht->append( infoKlient->getSpielerName( vonAccount ) );
                    nachricht->append( " hat deine Freundesanfrage abgelehnt." );
                    hauptScreen->lock();
                    nachLogin->zNachrichtenListe()->addNachricht( titel, nachricht, new Text( "Ok" ), 0, NachrichtType::nachricht, 0 );
                    hauptScreen->unlock();
                }
            }
            break;
        case 0xC: // Einladung zum Chatroom
            if( 1 )
            {
                int vonAccount = 0;
                empfangen->getNachrichtEncrypted( (char*)&vonAccount, 4 );
                int chatroomId = 0;
                empfangen->getNachrichtEncrypted( (char*)&chatroomId, 4 );
                if( nachLogin && nachLogin->zNachrichtenListe() )
                {
                    Text *titel = new Text( "Chatroom Einladung" );
                    Text *nachricht = new Text( "" );
                    nachricht->append( infoKlient->getSpielerName( vonAccount ) );
                    nachricht->append( " l�dt dich dazu ein das Chatroom '" );
                    nachricht->append( infoKlient->getChatroomName( chatroomId ) );
                    nachricht->append( "' zu betreten." );
                    ChatroomEinladungParam *param = new ChatroomEinladungParam();
                    param->chatroomId = chatroomId;
                    param->vonAccount = vonAccount;
                    nachLogin->zNachrichtenListe()->addNachricht( titel, nachricht, new Text( "betreten" ), new Text( "ablehnen" ), NachrichtType::chatroomEinladung, param );
                }
            }
            break;
        case 0xD: // Einladung zum Chatroom abgelehnt
            if( 1 )
            {
                int accountId = 0;
                empfangen->getNachrichtEncrypted( (char*)&accountId, 4 );
                int chatroomId = 0;
                empfangen->getNachrichtEncrypted( (char*)&chatroomId, 4 );
                if( nachLogin && nachLogin->zNachrichtenListe() )
                {
                    Text *titel = new Text( "Chatroom Einladung Abgelehnt" );
                    Text *nachricht = new Text( "" );
                    nachricht->append( infoKlient->getSpielerName( accountId ) );
                    nachricht->append( " m�chte dem Chatroom '" );
                    nachricht->append( infoKlient->getChatroomName( chatroomId ) );
                    nachricht->append( "' nicht beitreten." );
                    hauptScreen->lock();
                    nachLogin->zNachrichtenListe()->addNachricht( titel, nachricht, new Text( "Ok" ), 0, NachrichtType::nachricht, 0 );
                    hauptScreen->unlock();
                }
            }
            break;
        case 0xE: // Spieler betritt Chatroom
            if( 1 )
            {
                int chatroomId = 0;
                empfangen->getNachrichtEncrypted( (char*)&chatroomId, 4 );
                int accountId = 0;
                empfangen->getNachrichtEncrypted( (char*)&accountId, 4 );
                hauptScreen->lock();
                if( nachLogin && nachLogin->zChatLeiste() )
                    nachLogin->zChatLeiste()->addSpieler( chatroomId, accountId );
                hauptScreen->unlock();
            }
            break;
        case 0xF: // Chatroom Nachricht
            if( 1 )
            {
                int chatroomId = 0;
                empfangen->getNachrichtEncrypted( (char*)&chatroomId, 4 );
                int vonAccount = 0;
                empfangen->getNachrichtEncrypted( (char*)&vonAccount, 4 );
                char l�n = 0;
                empfangen->getNachrichtEncrypted( &l�n, 1 );
                char *nachricht = new char[ l�n + 1 ];
                nachricht[ l�n ] = 0;
                if( l�n )
                {
                    empfangen->getNachrichtEncrypted( nachricht, l�n );
                    hauptScreen->lock();
                    if( nachLogin && nachLogin->zChatLeiste() )
                        nachLogin->zChatLeiste()->chatroomNachricht( chatroomId, vonAccount, nachricht );
                    hauptScreen->unlock();
                }
                delete[]nachricht;
            }
            break;
        case 0x10: // Spieler verl�sst Chatroom
            if( 1 )
            {
                int chatroomId = 0;
                empfangen->getNachrichtEncrypted( (char*)&chatroomId, 4 );
                int accountId = 0;
                empfangen->getNachrichtEncrypted( (char*)&accountId, 4 );
                hauptScreen->lock();
                if( nachLogin && nachLogin->zChatLeiste() )
                    nachLogin->zChatLeiste()->removeSpieler( chatroomId, accountId );
                hauptScreen->unlock();
            }
            break;
        case 0x11: // Freunde
            if( 1 )
            {
                char freundeAnzahl;
                empfangen->getNachrichtEncrypted( &freundeAnzahl, 1 );
                for( int i = 0; i < freundeAnzahl; i++ )
                {
                    int accountId = 0;
                    empfangen->getNachrichtEncrypted( (char*)&accountId, 4 );
                    if( nachLogin )
                    {
                        while( !nachLogin->zFreundesListe() )
                        {
                            Sleep( 50 );
                        }
                        hauptScreen->lock();
                        nachLogin->zFreundesListe()->addMember( accountId );
                        hauptScreen->unlock();
                    }
                }
            }
            break;
        case 0x12: // Spieler im Chatroom
            if( 1 )
            {
                int chatroomId = 0;
                empfangen->getNachrichtEncrypted( (char*)&chatroomId, 4 );
                char anzahl = 0;
                empfangen->getNachrichtEncrypted( &anzahl, 1 );
                for( char i = 0; i < anzahl; i++ )
                {
                    int accountId = 0;
                    empfangen->getNachrichtEncrypted( (char*)&accountId, 4 );
                    hauptScreen->lock();
                    if( nachLogin && nachLogin->zChatLeiste() )
                        nachLogin->zChatLeiste()->addSpieler( chatroomId, accountId );
                    hauptScreen->unlock();
                }
            }
            break;
        case 0x13: // Freund online
            if( 1 )
            {
                int accountId = 0;
                empfangen->getNachrichtEncrypted( (char*)&accountId, 4 );
                hauptScreen->lock();
                if( nachLogin && nachLogin->zFreundesListe() )
                    nachLogin->zFreundesListe()->setOnline( accountId, 1 );
                hauptScreen->unlock();
            }
            break;
        case 0x14: // Freund offline
            if( 1 )
            {
                int accountId = 0;
                empfangen->getNachrichtEncrypted( (char*)&accountId, 4 );
                hauptScreen->lock();
                if( nachLogin && nachLogin->zFreundesListe() )
                    nachLogin->zFreundesListe()->setOnline( accountId, 0 );
                hauptScreen->unlock();
            }
            break;
        case 0x15: // Chatroom Admin
            if( 1 )
            {
                int chatroomId = 0;
                empfangen->getNachrichtEncrypted( (char*)&chatroomId, 4 );
                hauptScreen->lock();
                if( nachLogin && nachLogin->zChatLeiste() )
                    nachLogin->zChatLeiste()->setChatroomAdmin( chatroomId );
                hauptScreen->unlock();
            }
            break;
        case 0x16: // Chatroom Kick
            if( 1 )
            {
                int chatroomId = 0;
                empfangen->getNachrichtEncrypted( (char*)&chatroomId, 4 );
                hauptScreen->lock();
                if( nachLogin && nachLogin->zChatLeiste() )
                    nachLogin->zChatLeiste()->removeChat( 0, chatroomId );
                hauptScreen->unlock();
            }
            break;
        case 0x17: // Spieler betritt Gruppe
            if( 1 )
            {
                int accountId = 0;
                int gruppeId = 0;
                empfangen->getNachrichtEncrypted( (char*)&accountId, 4 );
                empfangen->getNachrichtEncrypted( (char*)&gruppeId, 4 );
                if( nachLogin && nachLogin->zSpielenFenster() )
                    nachLogin->zSpielenFenster()->spielerBetrittGruppe( gruppeId, accountId );
            }
            break;
        case 0x18: // Spieler verl�sst Gruppe
            if( 1 )
            {
                int accountId = 0;
                int gruppeId = 0;
                empfangen->getNachrichtEncrypted( (char*)&accountId, 4 );
                empfangen->getNachrichtEncrypted( (char*)&gruppeId, 4 );
                if( nachLogin && nachLogin->zSpielenFenster() )
                    nachLogin->zSpielenFenster()->spielerVerl�sstGruppe( gruppeId, accountId );
            }
            break;
        case 0x19: // gruppe Nachricht
            if( 1 )
            {
                int gruppeId = 0;
                char l�n = 0;
                empfangen->getNachrichtEncrypted( (char*)&gruppeId, 4 );
                empfangen->getNachrichtEncrypted( &l�n, 1 );
                if( l�n )
                {
                    char *nachricht = new char[ l�n + 1 ];
                    nachricht[ l�n ] = 0;
                    empfangen->getNachrichtEncrypted( nachricht, l�n );
                    if( nachLogin && nachLogin->zSpielenFenster() )
                        nachLogin->zSpielenFenster()->gruppeNachricht( gruppeId, nachricht );
                    delete[] nachricht;
                }
            }
            break;
        case 0x1A: // gruppe Angemeldet
            if( 1 )
            {
                int gruppeId = 0;
                empfangen->getNachrichtEncrypted( (char*)&gruppeId, 4 );
                if( nachLogin && nachLogin->zSpielenFenster() )
                    nachLogin->zSpielenFenster()->gruppeAnmelden( gruppeId );
            }
            break;
        case 0x1B: // gruppe Abgemeldet
            if( 1 )
            {
                int gruppeId = 0;
                empfangen->getNachrichtEncrypted( (char*)&gruppeId, 4 );
                if( nachLogin && nachLogin->zSpielenFenster() )
                    nachLogin->zSpielenFenster()->gruppeAbmelden( gruppeId );
            }
            break;
        case 0x1C: // gruppe Spiel starten
            if( 1 )
            {
                int gruppeId = 0;
                char starten = 0;
                empfangen->getNachrichtEncrypted( (char*)&gruppeId, 4 );
                empfangen->getNachrichtEncrypted( &starten, 1 );
                if( nachLogin && nachLogin->zSpielenFenster() )
                    nachLogin->zSpielenFenster()->setGruppeSpielStarten( gruppeId, starten == 1 );
            }
            break;
        case 0x1D: // kick aus Gruppe
            if( 1 )
            {
                int gruppeId = 0;
                empfangen->getNachrichtEncrypted( (char*)&gruppeId, 4 );
                if( nachLogin && nachLogin->zSpielenFenster() )
                    nachLogin->zSpielenFenster()->kickAusGruppe( gruppeId );
            }
            break;
        case 0x1E: // gruppe Admin
            if( 1 )
            {
                int gruppeId = 0;
                int adminId = 0;
                empfangen->getNachrichtEncrypted( (char*)&gruppeId, 4 );
                empfangen->getNachrichtEncrypted( (char*)&adminId, 4 );
                if( nachLogin && nachLogin->zSpielenFenster() )
                    nachLogin->zSpielenFenster()->setGruppeAdmin( gruppeId, adminId );
            }
            break;
        case 0x1F: // gruppe Einladung abgelehnt
            if( 1 )
            {
                int gruppeId;
                int accountId;
                empfangen->getNachrichtEncrypted( (char*)&gruppeId, 4 );
                empfangen->getNachrichtEncrypted( (char*)&accountId, 4 );
                if( nachLogin && nachLogin->zSpielenFenster() )
                    nachLogin->zSpielenFenster()->gruppeEinadungAbgelehnt( gruppeId, accountId );
            }
            break;
        case 0x20: // SpielServer Verbindungs Anfrage
            if( 1 )
            {
                unsigned short port;
                unsigned char *ip = new unsigned char[ 4 ];
                empfangen->getNachrichtEncrypted( (char*)&port, 2 );
                empfangen->getNachrichtEncrypted( (char*)ip, 4 );
                Text *ipT = new Text( "" );
                ipT->append( (int)ip[ 0 ] );
                ipT->append( "." );
                ipT->append( (int)ip[ 1 ] );
                ipT->append( "." );
                ipT->append( (int)ip[ 2 ] );
                ipT->append( "." );
                ipT->append( (int)ip[ 3 ] );
                spielKlient->verbinde( port, ipT->getText() );
                delete[] ip;
                ipT->release();
            }
            break;
        case 0x21: // Gruppe Einladung abgebrochen
            if( 1 )
            {
                int gruppeId = 0;
                int account = 0;
                empfangen->getNachrichtEncrypted( (char*)&gruppeId, 4 );
                empfangen->getNachrichtEncrypted( (char*)&account, 4 );
                if( nachLogin && nachLogin->zSpielenFenster() )
                    nachLogin->zSpielenFenster()->gruppeEinladungAbgebrochen( gruppeId, account );
            }
            break;
        case 0x22: // Gruppe Einladung hinzuf�gen
            if( 1 )
            {
                int gruppeId = 0;
                int account = 0;
                empfangen->getNachrichtEncrypted( (char*)&gruppeId, 4 );
                empfangen->getNachrichtEncrypted( (char*)&account, 4 );
                if( nachLogin && nachLogin->zSpielenFenster() )
                    nachLogin->zSpielenFenster()->gruppeEinladungNeu( gruppeId, account );
            }
            break;
        case 0x23: // ping
            empfangen->sendeEncrypted( "\1", 1 );
            break;
        default: // Unbekannte Servernachricht
            if( nachLogin && nachLogin->zNachrichtenListe() )
            {
                hauptScreen->lock();
                nachLogin->zNachrichtenListe()->addNachricht( new Text( "Fehler" ),
                                                              new Text( "Unbekannte Nachricht vom Server. Eventuel ist der Client nicht mehr Aktuell." ),
                                                              new Text( "Ok" ), 0, NachrichtType::nachricht, 0 );
                hauptScreen->unlock();
            }
            break;
        }
    }
}

// constant
bool ChatKlient::istVerbunden() const // pr�ft, ob mit Chat Server verbunden
{
    return verbunden;
}

char *ChatKlient::getLetzterFehler() const // gibt den Letzten Fehlertext zu�ck
{
    return fehler->getText();
}

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

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