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

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

// Destruktor 
ChatKlient::~ChatKlient()
{
    LOCK( &cs );
    if( senden )
    {
        char serverReturn = 0;
        if( verbunden )
        {
            senden->sendeVerschlüsselt( "\4", 1 );
            senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
            senden->sendeVerschlüsselt( "\3", 1 );
            senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
            senden->trenne();
        }
        senden = senden->release();
        verbunden = 0;
        if( empfangen )
        {
            warteAufThread( 5000 );
            ende();
            empfangen->trenne();
            empfangen = empfangen->release();
        }
    }
    fehler = fehler->release();
    UNLOCK( &cs );
    DeleteCriticalSection( &cs );
}

// nicht constant
bool ChatKlient::verbinde() // verbindet ich mit dem Chat Server
{
    LOCK( &cs );
    if( verbunden )
    {
        UNLOCK( &cs );
        return 1;
    }
    if( !senden )
    {
        char *msIp = getMainServerIp();
        unsigned short msPort = getMainServerPort();
        senden = new Klient();
        unsigned char schlüssel[ 20 ] = { 199, 164, 172, 55, 246, 16, 155, 8, 151, 176, 250, 181, 227, 133, 30, 41, 200, 26, 7, 151 };
        senden->setSendeSchlüssel( (char*)schlüssel, 20 );
        senden->setEmpfangSchlüssel( (char*)schlüssel, 20 );
        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;
            UNLOCK( &cs );
            return 0;
        }
        delete[]msIp;
        senden->sende( "\0", 1 ); // Verschlüsselung aktivieren
        senden->sendeVerschlüsselt( "\1", 1 );
        senden->sendeVerschlüsselt( (char*)&klientId, 4 );
        char serverReturn = 0;
        senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
        if( serverReturn == 3 )
        {
            char län = 0;
            senden->getNachrichtVerschlüsselt( &län, 1 );
            char *nachricht = new char[ län + 1 ];
            nachricht[ län ] = 0;
            senden->getNachrichtVerschlüsselt( nachricht, län );
            fehler->setText( nachricht );
            delete[]nachricht;
            senden->sendeVerschlüsselt( "\3", 1 );
            senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
            senden->trenne();
            senden = senden->release();
            UNLOCK( &cs );
            return 0;
        }
        char *sl = 0;
        char slLän = getSchlüssel( &sl );
        senden->setSendeSchlüssel( sl, slLän );
        senden->setEmpfangSchlüssel( sl, slLän );
        delete[] sl;
        senden->sendeVerschlüsselt( "\6\5", 2 );
        char byte = 0;
        senden->getNachrichtVerschlüsselt( &byte, 1 );
        if( byte == 2 )
        {
            unsigned char lsIp[ 4 ];
            senden->getNachrichtVerschlüsselt( (char *)lsIp, 4 );
            unsigned short lsPort = 0;
            senden->getNachrichtVerschlüsselt( (char*)&lsPort, 2 );
            senden->sendeVerschlüsselt( "\3", 1 );
            senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
            senden->trenne();
            Text *lsIpT = new Text( "" );
            lsIpT->anhängen( (int)lsIp[ 0 ] );
            lsIpT->anhängen( "." );
            lsIpT->anhängen( (int)lsIp[ 1 ] );
            lsIpT->anhängen( "." );
            lsIpT->anhängen( (int)lsIp[ 2 ] );
            lsIpT->anhängen( "." );
            lsIpT->anhängen( (int)lsIp[ 3 ] );
            unsigned char schlüssel[ 20 ] = { 79, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
            senden->setSendeSchlüssel( (char*)schlüssel, 20 );
            senden->setEmpfangSchlüssel( (char*)schlüssel, 20 );
            senden->verbinde( lsPort, lsIpT->getText() );
            lsIpT = lsIpT->release();
            senden->sendeVerschlüsselt( "\3", 1 );
            if( !senden->hatNachricht( 5000 ) )
                MessageBox( 0, "Der Server antwortet nicht.", "Fehler", MB_ICONERROR );
            else
                senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
            senden->trenne();
        }
        if( byte == 3 )
        {
            senden->getNachrichtVerschlüsselt( &byte, 1 );
            char *f = new char[ byte + 1 ];
            f[ byte ] = 0;
            senden->getNachrichtVerschlüsselt( f, byte );
            fehler->setText( f );
            delete[]f;
            senden->sendeVerschlüsselt( "\3", 1 );
            senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
            senden->trenne();
            senden = senden->release();
            UNLOCK( &cs );
            return 0;
        }
    }
    unsigned char schlüssel[ 20 ] = { 79, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
    senden->setSendeSchlüssel( (char*)schlüssel, 20 );
    senden->setEmpfangSchlüssel( (char*)schlüssel, 20 );
    if( senden->verbinde( senden->getServerPort(), senden->getServerIp() ) )
    {
        if( senden->sendeVerschlüsselt( "\1", 1 ) )
        {
            senden->sendeVerschlüsselt( (char*)&klientId, 4 );
            char ret = 0;
            senden->getNachrichtVerschlüsselt( &ret, 1 );
            if( ret != 1 )
            {
                char byte = 0;
                senden->getNachrichtVerschlüsselt( &byte, 1 );
                char *f = new char[ byte + 1 ];
                f[ byte ] = 0;
                senden->getNachrichtVerschlüsselt( f, byte );
                fehler->setText( f );
                delete[]f;
                senden->sendeVerschlüsselt( "\3", 1 );
                char serverReturn = 0;
                senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
                senden->trenne();
                UNLOCK( &cs );
                return 0;
            }
            char *sl = 0;
            char slLän = getSchlüssel( &sl );
            senden->setSendeSchlüssel( sl, slLän );
            senden->setEmpfangSchlüssel( sl, slLän );
            delete[] sl;
            if( !empfangen )
                empfangen = new Klient();
            unsigned char schlüssel[ 20 ] = { 79, 20, 190, 133, 10, 175, 51, 96, 62, 1, 180, 194, 126, 50, 211, 154, 105, 227, 22, 101 };
            empfangen->setSendeSchlüssel( (char*)schlüssel, 20 );
            empfangen->setEmpfangSchlüssel( (char*)schlüssel, 20 );
            if( empfangen->verbinde( senden->getServerPort(), senden->getServerIp() ) )
            {
                start();
                verbunden = 1;
                UNLOCK( &cs );
                return 1;
            }
            else
            {
                fehler->setText( "Der dir zugewiesene Chat Server kann dir keine Nachrichten senden." );
                UNLOCK( &cs );
                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();
    }
    UNLOCK( &cs );
    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 = textLänge( nachricht );
    if( !län )
        return 1;
    LOCK( &cs );
    senden->sendeVerschlüsselt( "\6", 1 );
    char serverReturn = 0;
    senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeVerschlüsselt( (char*)&zuAccount, 4 );
        senden->sendeVerschlüsselt( &län, 1 );
        senden->sendeVerschlüsselt( nachricht, län );
    }
    else
    {
        UNLOCK( &cs );
        return 0;
    }
    UNLOCK( &cs );
    return 1;
}

bool ChatKlient::accountNameÄndern( const char *name ) // ändert den Account Namen
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    char län = textLänge( name );
    if( !län )
        return 1;
    LOCK( &cs );
    senden->sendeVerschlüsselt( "\x8", 1 );
    char serverReturn = 0;
    senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeVerschlüsselt( &län, 1 );
        senden->sendeVerschlüsselt( name, län );
        senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
        UNLOCK( &cs );
        return serverReturn == 1;
    }
    else
    {
        UNLOCK( &cs );
        return 0;
    }
}

bool ChatKlient::freundschaftBeenden( int accountId ) // beendet die Freundschaft mit einem Account
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    LOCK( &cs );
    senden->sendeVerschlüsselt( "\x9", 1 );
    char serverReturn = 0;
    senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeVerschlüsselt( (char*)&accountId, 4 );
        senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
        UNLOCK( &cs );
        return serverReturn == 1;
    }
    else
    {
        UNLOCK( &cs );
        return 0;
    }
}

bool ChatKlient::freundesAnfrage( int accountId ) // sendet eine Freundesanfragezu einem Account
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    LOCK( &cs );
    senden->sendeVerschlüsselt( "\xA", 1 );
    char serverReturn = 0;
    senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeVerschlüsselt( (char*)&accountId, 4 );
        senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
        UNLOCK( &cs );
        return serverReturn == 1;
    }
    else
    {
        UNLOCK( &cs );
        return 0;
    }
}

bool ChatKlient::freundesAnfrageBeantworten( int accountId, bool ja ) // beantwortet eine Freundesanfrage
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    LOCK( &cs );
    senden->sendeVerschlüsselt( "\xB", 1 );
    char serverReturn = 0;
    senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeVerschlüsselt( (char*)&accountId, 4 );
        char ok = (char)ja;
        senden->sendeVerschlüsselt( &ok, 1 );
        senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
        UNLOCK( &cs );
        return serverReturn == 1;
    }
    else
    {
        UNLOCK( &cs );
        return 0;
    }
}

int ChatKlient::chatroomErstellen( const char *name ) // erstellt ein chatroom
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    char län = textLänge( name );
    if( !län )
        return 0;
    LOCK( &cs );
    senden->sendeVerschlüsselt( "\xC", 1 );
    char serverReturn = 0;
    senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeVerschlüsselt( &län, 1 );
        senden->sendeVerschlüsselt( name, län );
        senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
        if( !serverReturn )
        {
            UNLOCK( &cs );
            return 0;
        }
        int ret = 0;
        senden->getNachrichtVerschlüsselt( (char*)&ret, 4 );
        UNLOCK( &cs );
        return ret;
    }
    else
    {
        UNLOCK( &cs );
        return 0;
    }
}

bool ChatKlient::chatroomEinladung( int accountId, int chatroomId ) // verschickt eine Einladung zu einem Chatroom
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    LOCK( &cs );
    senden->sendeVerschlüsselt( "\xD", 1 );
    char serverReturn = 0;
    senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeVerschlüsselt( (char*)&accountId, 4 );
        senden->sendeVerschlüsselt( (char*)&chatroomId, 4 );
        senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
        UNLOCK( &cs );
        return serverReturn == 1;
    }
    else
    {
        UNLOCK( &cs );
        return 0;
    }
}

bool ChatKlient::chatroomEinladungAblehnen( int accountId, int chatroomId ) // Einladung zum Chatroom wird abgelehnt
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    LOCK( &cs );
    senden->sendeVerschlüsselt( "\xE", 1 );
    char serverReturn = 0;
    senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeVerschlüsselt( (char*)&accountId, 4 );
        senden->sendeVerschlüsselt( (char*)&chatroomId, 4 );
        senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
        UNLOCK( &cs );
        return serverReturn == 1;
    }
    else
    {
        UNLOCK( &cs );
        return 0;
    }
}

bool ChatKlient::chatroomBetreten( int chatroomId ) // betritt ein chatroom
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    LOCK( &cs );
    senden->sendeVerschlüsselt( "\xF", 1 );
    char serverReturn = 0;
    senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeVerschlüsselt( (char*)&chatroomId, 4 );
        senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
        UNLOCK( &cs );
        return serverReturn == 1;
    }
    else
    {
        UNLOCK( &cs );
        return 0;
    }
}

bool ChatKlient::chatroomNachricht( int chatroomId, const char *nachricht ) // chatroom Nachricht senden
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    char län = textLänge( nachricht );
    if( !län )
        return 0;
    LOCK( &cs );
    senden->sendeVerschlüsselt( "\x10", 1 );
    char serverReturn = 0;
    senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeVerschlüsselt( (char*)&chatroomId, 4 );
        senden->sendeVerschlüsselt( &län, 1 );
        senden->sendeVerschlüsselt( nachricht, län );
        senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
        UNLOCK( &cs );
        return serverReturn == 1;
    }
    else
    {
        UNLOCK( &cs );
        return 0;
    }
}

bool ChatKlient::chatroomVerlassen( int chatroomId ) // verlässt chatroom
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    LOCK( &cs );
    senden->sendeVerschlüsselt( "\x11", 1 );
    char serverReturn = 0;
    senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeVerschlüsselt( (char*)&chatroomId, 4 );
        senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
        UNLOCK( &cs );
        return serverReturn == 1;
    }
    else
    {
        UNLOCK( &cs );
        return 0;
    }
}

bool ChatKlient::chatroomKick( int chatroomId, int accountId ) // kickt Spieler aus Chatroom( nur wenn admin )
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    LOCK( &cs );
    senden->sendeVerschlüsselt( "\x12", 1 );
    char serverReturn = 0;
    senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
    if( serverReturn )
    {
        senden->sendeVerschlüsselt( (char*)&chatroomId, 4 );
        senden->sendeVerschlüsselt( (char*)&accountId, 4 );
        senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
        UNLOCK( &cs );
        return serverReturn == 1;
    }
    else
    {
        UNLOCK( &cs );
        return 0;
    }
}

bool ChatKlient::freundesListeAnfragen() // fragt nach allen freunden
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    char serverReturn = 0;
    LOCK( &cs );
    senden->sendeVerschlüsselt( "\x13", 1 );
    senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
    UNLOCK( &cs );
    return serverReturn == 1;
}

bool ChatKlient::chatNachrichtAnfrage() // fragt nach chat nachrichten in abwesenheit
{
    if( !verbunden )
        verbinde();
    if( !verbunden )
        return 0;
    char serverReturn = 0;
    LOCK( &cs );
    senden->sendeVerschlüsselt( "\x14", 1 );
    senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
    UNLOCK( &cs );
    return serverReturn == 1;
}

bool ChatKlient::keepAlive() // Erhält die Verbindung aufrecht
{
    if( !verbunden )
        return 0;
    char res = 0;
    if( !TryEnterCriticalSection( &cs ) )
        return 1;
    senden->sendeVerschlüsselt( "\x15", 1 );
    senden->getNachrichtVerschlüsselt( &res, 1 );
    UNLOCK( &cs );
    if( res != 1 )
        trenne();
    return res == 1;
}

bool ChatKlient::trenne() // trennt sich von dem Chat Server
{
    if( !verbunden )
        return 1;
    LOCK( &cs );
    senden->sendeVerschlüsselt( "\3", 1 );
    char serverReturn = 0;
    senden->getNachrichtVerschlüsselt( &serverReturn, 1 );
    senden->trenne();
    verbunden = 0;
    warteAufThread( 5000 );
    ende();
    if( empfangen )
        empfangen->trenne();
    UNLOCK( &cs );
    return 1;
}

void ChatKlient::thread() // empfangen von Nachrichten
{
    if( !verbunden || !empfangen || !senden )
        return;
    empfangen->sendeVerschlüsselt( "\1", 1 );
    empfangen->sendeVerschlüsselt( (char*)&klientId, 4 );
    char res = 0;
    empfangen->getNachrichtVerschlüsselt( &res, 1 );
    if( res == 3 )
    {
        char län = 0;
        senden->getNachrichtVerschlüsselt( &län, 1 );
        char *nachricht = new char[ län + 1 ];
        nachricht[ län ] = 0;
        senden->getNachrichtVerschlüsselt( 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->setSendeSchlüssel( sl, slLän );
    empfangen->setEmpfangSchlüssel( sl, slLän );
    delete[] sl;
    char befehl = 0;
    while( verbunden )
    {
        if( !empfangen->getNachrichtVerschlüsselt( &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->getNachrichtVerschlüsselt( &länge, 1 );
                char *txt = new char[ länge + 1 ];
                txt[ länge ] = 0;
                empfangen->getNachrichtVerschlüsselt( 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->getNachrichtVerschlüsselt( (char*)&vonAccount, 4 );
                char länge = 0;
                empfangen->getNachrichtVerschlüsselt( &länge, 1 );
                char *nachricht = new char[ länge + 1 ];
                nachricht[ länge ] = 0;
                empfangen->getNachrichtVerschlüsselt( 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->getNachrichtVerschlüsselt( (char*)&vonAccount, 4 );
                int gruppeId = 0;
                empfangen->getNachrichtVerschlüsselt( (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->anhängen( name );
                    nachricht->anhängen( "\nSpiel: " );
                    nachricht->anhängen( spiel );
                    nachricht->anhängen( "\nKarte: " );
                    nachricht->anhängen( 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->getNachrichtVerschlüsselt( (char*)&accountId, 4 );
                char län = 0;
                empfangen->getNachrichtVerschlüsselt( &län, 1 );
                char *status = new char[ län + 1 ];
                status[ län ] = 0;
                empfangen->getNachrichtVerschlüsselt( 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->getNachrichtVerschlüsselt( (char*)&accountId, 4 );
                char län = 0;
                empfangen->getNachrichtVerschlüsselt( &län, 1 );
                char *name = new char[ län + 1 ];
                name[ län ] = 0;
                empfangen->getNachrichtVerschlüsselt( 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->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( (char*)&vonAccount, 4 );
                if( nachLogin->zNachrichtenListe() )
                {
                    Text *titel = new Text( "Freundeseinladung" );
                    Text *nachricht = new Text( "" );
                    nachricht->anhängen( infoKlient->getSpielerName( vonAccount ) );
                    nachricht->anhängen( " 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->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( (char*)&vonAccount, 4 );
                if( nachLogin && nachLogin->zNachrichtenListe() )
                {
                    Text *titel = new Text( "Freundeseinladung Abgelehnt" );
                    Text *nachricht = new Text( "" );
                    nachricht->anhängen( infoKlient->getSpielerName( vonAccount ) );
                    nachricht->anhängen( " 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->getNachrichtVerschlüsselt( (char*)&vonAccount, 4 );
                int chatroomId = 0;
                empfangen->getNachrichtVerschlüsselt( (char*)&chatroomId, 4 );
                if( nachLogin && nachLogin->zNachrichtenListe() )
                {
                    Text *titel = new Text( "Chatroom Einladung" );
                    Text *nachricht = new Text( "" );
                    nachricht->anhängen( infoKlient->getSpielerName( vonAccount ) );
                    nachricht->anhängen( " lädt dich dazu ein das Chatroom '" );
                    nachricht->anhängen( infoKlient->getChatroomName( chatroomId ) );
                    nachricht->anhängen( "' 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->getNachrichtVerschlüsselt( (char*)&accountId, 4 );
                int chatroomId = 0;
                empfangen->getNachrichtVerschlüsselt( (char*)&chatroomId, 4 );
                if( nachLogin && nachLogin->zNachrichtenListe() )
                {
                    Text *titel = new Text( "Chatroom Einladung Abgelehnt" );
                    Text *nachricht = new Text( "" );
                    nachricht->anhängen( infoKlient->getSpielerName( accountId ) );
                    nachricht->anhängen( " möchte dem Chatroom '" );
                    nachricht->anhängen( infoKlient->getChatroomName( chatroomId ) );
                    nachricht->anhängen( "' 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->getNachrichtVerschlüsselt( (char*)&chatroomId, 4 );
                int accountId = 0;
                empfangen->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( (char*)&chatroomId, 4 );
                int vonAccount = 0;
                empfangen->getNachrichtVerschlüsselt( (char*)&vonAccount, 4 );
                char län = 0;
                empfangen->getNachrichtVerschlüsselt( &län, 1 );
                char *nachricht = new char[ län + 1 ];
                nachricht[ län ] = 0;
                if( län )
                {
                    empfangen->getNachrichtVerschlüsselt( 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->getNachrichtVerschlüsselt( (char*)&chatroomId, 4 );
                int accountId = 0;
                empfangen->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( &freundeAnzahl, 1 );
                for( int i = 0; i < freundeAnzahl; i++ )
                {
                    int accountId = 0;
                    empfangen->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( (char*)&chatroomId, 4 );
                char anzahl = 0;
                empfangen->getNachrichtVerschlüsselt( &anzahl, 1 );
                for( char i = 0; i < anzahl; i++ )
                {
                    int accountId = 0;
                    empfangen->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( (char*)&accountId, 4 );
                empfangen->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( (char*)&accountId, 4 );
                empfangen->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( (char*)&gruppeId, 4 );
                empfangen->getNachrichtVerschlüsselt( &län, 1 );
                if( län )
                {
                    char *nachricht = new char[ län + 1 ];
                    nachricht[ län ] = 0;
                    empfangen->getNachrichtVerschlüsselt( 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->getNachrichtVerschlüsselt( (char*)&gruppeId, 4 );
                if( nachLogin && nachLogin->zSpielenFenster() )
                    nachLogin->zSpielenFenster()->gruppeAnmelden( gruppeId );
            }
            break;
        case 0x1B: // gruppe Abgemeldet
            if( 1 )
            {
                int gruppeId = 0;
                empfangen->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( (char*)&gruppeId, 4 );
                empfangen->getNachrichtVerschlüsselt( &starten, 1 );
                if( nachLogin && nachLogin->zSpielenFenster() )
                    nachLogin->zSpielenFenster()->setGruppeSpielStarten( gruppeId, starten == 1 );
            }
            break;
        case 0x1D: // kick aus Gruppe
            if( 1 )
            {
                int gruppeId = 0;
                empfangen->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( (char*)&gruppeId, 4 );
                empfangen->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( (char*)&gruppeId, 4 );
                empfangen->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( (char*)&port, 2 );
                empfangen->getNachrichtVerschlüsselt( (char*)ip, 4 );
                Text *ipT = new Text( "" );
                ipT->anhängen( (int)ip[ 0 ] );
                ipT->anhängen( "." );
                ipT->anhängen( (int)ip[ 1 ] );
                ipT->anhängen( "." );
                ipT->anhängen( (int)ip[ 2 ] );
                ipT->anhängen( "." );
                ipT->anhängen( (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->getNachrichtVerschlüsselt( (char*)&gruppeId, 4 );
                empfangen->getNachrichtVerschlüsselt( (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->getNachrichtVerschlüsselt( (char*)&gruppeId, 4 );
                empfangen->getNachrichtVerschlüsselt( (char*)&account, 4 );
                if( nachLogin && nachLogin->zSpielenFenster() )
                    nachLogin->zSpielenFenster()->gruppeEinladungNeu( gruppeId, account );
            }
            break;
        case 0x23: // ping
            empfangen->sendeVerschlüsselt( "\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;
}