#pragma once
#include <Klient.h>
#include <iostream>
#include <Text.h>
#include "Keys.h"
#include "ESClient.h"

#define MAIN_SERVER_PORT 5225
#define MAIN_SERVER_IP "94.130.27.12"

#define ACCOUNT_NAME "Test"
#define ACCOUNT_PASSWORD "t"

class MSClient
{
private:
    Network::Klient *k;
    char *key;
    unsigned char keyLen;
    int cId;
    unsigned short port;
    
public:
    MSClient()
    {
        k = 0;
        key = 0;
        keyLen = 0;
        cId = 0;
        port = 0;
    }

    ~MSClient()
    {
        if( k )
            k->release();
        delete[] key;
    }

    bool registerSSL()
    {
        Network::SSLKlient *klientSSL = new Network::SSLKlient();
        int l = 0;
        if( !klientSSL->verbinde( MAIN_SERVER_PORT, MAIN_SERVER_IP ) )
        {
            std::cerr << "error while trying to connect to Main SSL Server\n";
            klientSSL->release();
            return 0;
        }
        klientSSL->sende( "\1", 5 );
        char byte = 0;
        klientSSL->getNachricht( &byte, 1 );
        if( byte == 3 )
        {
            klientSSL->getNachricht( &byte, 1 );
            char *message = new char[ byte + 1 ];
            message[ byte ] = 0;
            klientSSL->getNachricht( message, byte );
            std::cerr << "error while register new client server returned: " << message << "\n";
            delete[]message;
            klientSSL->sende( "\3", 1 );
            klientSSL->getNachricht( &byte, 1 );
            klientSSL->trenne();
            klientSSL->release();
            return 0;
        }
        if( byte == 1 )
        {
            klientSSL->getNachricht( (char*)&port, 4 );
            klientSSL->getNachricht( (char*)&cId, 4 );
            klientSSL->getNachricht( (char*)&keyLen, 1 );
            if( keyLen )
            {
                key = new char[ keyLen ];
                klientSSL->getNachricht( key, keyLen );
            }
        }
        klientSSL->sende( "\3", 1 );
        klientSSL->getNachricht( &byte, 1 );
        klientSSL->trenne();
        klientSSL->release();
        return 1;
    }

    bool connect()
    {
        if( k )
            return 1;
        k = new Network::Klient(); 
        int l = 0;
        char *key;
        Keys::getServerKey( &key, l, Keys::MAIN, Keys::SENDEN );
        k->setSendeKey( key, l );
        delete[] key;
        Keys::getServerKey( &key, l, Keys::MAIN, Keys::EMPFANGEN );
        k->setEmpfangKey( key, l );
        delete[] key;
        if( !k->verbinde( port, MAIN_SERVER_IP ) )
        {
            std::cerr << "error while trying to connect to Main Server\n";
            k = k->release();
            return 0;
        }
        k->sende( "\0", 1 ); // Verschlüsselung aktivieren
        k->sendeEncrypted( "\1", 1 );
        k->sendeEncrypted( (char*)&cId, 4 );
        char serverReturn = 0;
        k->getNachrichtEncrypted( &serverReturn, 1 );
        if( serverReturn == 3 )
        {
            k->getNachrichtEncrypted( &serverReturn, 1 );
            char *message = new char[ serverReturn + 1 ];
            message[ serverReturn ] = 0;
            k->getNachrichtEncrypted( message, serverReturn );
            std::cerr << "error while trying to identify registered client server returned: " << message << "\n";
            delete[] message;
            k->sendeEncrypted( "\3", 1 );
            k->getNachrichtEncrypted( &serverReturn, 1 );
            k->trenne();
            k = k->release();
            return 0;
        }
        else
        {
            k->setSendeKey( this->key, keyLen );
            k->setEmpfangKey( this->key, keyLen );
            return 1;
        }
    }

    ESClient *createErhaltungServerClient()
    {
        connect();
        if( !k )
        {
            std::cerr << "no connection to Main Server\n";
            return 0;
        }
        k->sendeEncrypted( "\6\x8", 2 );
        char byte = 0;
        k->getNachrichtEncrypted( &byte, 1 );
        if( byte == 2 )
        {
            unsigned char lsIp[ 4 ];
            k->getNachrichtEncrypted( (char *)lsIp, 4 );
            unsigned short lsPort = 0;
            k->getNachrichtEncrypted( (char*)&lsPort, 2 );
            k->sendeEncrypted( "\3", 1 );
            k->getNachrichtEncrypted( &byte, 1 );
            k->trenne();
            Framework::Text ipT;
            ipT += (int)lsIp[ 0 ];
            ipT += ".";
            ipT += (int)lsIp[ 1 ];
            ipT += ".";
            ipT += (int)lsIp[ 2 ];
            ipT += ".";
            ipT += (int)lsIp[ 3 ];
            int l = 0;
            return new ESClient( cId, port, ipT, key, keyLen );
        }
        else if( byte == 3 )
        {
            k->getNachrichtEncrypted( &byte, 1 );
            char *f = new char[ byte + 1 ];
            f[ byte ] = 0;
            k->getNachrichtEncrypted( f, byte );
            std::cerr << "error while requesting ErhaltungServer server returned: " << f << "\n";
            delete[]f;
        }
        return 0;
    }

    bool unregister()
    {
        connect();
        if( !k )
        {
            std::cerr << "no connection to Main Server\n";
            return 0;
        }
        k->sendeEncrypted( "\7", 1 );
        char serverReturn = 0;
        k->getNachrichtEncrypted( &serverReturn, 1 );
        if( serverReturn == 3 )
        {
            k->getNachrichtEncrypted( &serverReturn, 1 );
            char *message = new char[ serverReturn + 1 ];
            message[ serverReturn ] = 0;
            k->getNachrichtEncrypted( message, serverReturn );
            std::cerr << "error while trying to unregistere client server returned: " << message << "\n";
            delete[] message;
            k->sendeEncrypted( "\3", 1 );
            k->getNachrichtEncrypted( &serverReturn, 1 );
            k->trenne();
            k = k->release();
            return 0;
        }
        k->sendeEncrypted( "\3", 1 );
        k->getNachrichtEncrypted( &serverReturn, 1 );
        k->trenne();
        k = k->release();
        cId = 0;
        delete key;
        key = 0;
        keyLen = 0;
        return 1;
    }
};