#include "Netzwerk.h"
#include "Keys.h"

// Inhalt der ErhaltungKlient Klasse aus Netzwerk.h
// Konstruktor
ErhaltungKlient::ErhaltungKlient( int klientId )
: Thread()
{
	klient = 0;
	this->klientId = klientId;
	abmel = 0;
	trenn = 0;
	ref = 1;
}

// Destruktor
ErhaltungKlient::~ErhaltungKlient()
{
	ende();
	if( klient )
		klient->release();
}

// nicht constant
void ErhaltungKlient::verbinden( int mSP, Text *zMSIp, char *netwSchlüssel, char netwSchlüsselLän )
{
	if( !klient )
	{
		klient = new Klient();
        int l = 0;
        char *key;
        Keys::getServerKey( &key, l, Keys::MAIN, Keys::SENDEN );
        klient->setSendeKey( key, l );
        delete[] key;
        Keys::getServerKey( &key, l, Keys::MAIN, Keys::EMPFANGEN );
        klient->setEmpfangKey( key, l );
        delete[] key;
		if( !klient->verbinde( mSP, zMSIp->getText() ) )
		{
			klient = klient->release();
			return;
		}
		klient->sende( "\0", 1 ); // Verschlüsselung aktivieren
		klient->sendeEncrypted( "\1", 1 );
		klient->sendeEncrypted( (char*)&klientId, 4 );
		char serverReturn = 0;
		klient->getNachrichtEncrypted( &serverReturn, 1 );
		if( serverReturn == 3 )
		{
			char län = 0;
			klient->getNachrichtEncrypted( &län, 1 );
			char *nachricht = new char[ län + 1 ];
			nachricht[ län ] = 0;
			klient->getNachrichtEncrypted( nachricht, län );
			delete[]nachricht;
			klient->sendeEncrypted( "\3", 1 );
			klient->getNachrichtEncrypted( &serverReturn, 1 );
			klient->trenne();
			klient = klient->release();
			return;
		}
		klient->setSendeKey( (char*)netwSchlüssel, netwSchlüsselLän );
		klient->setEmpfangKey( (char*)netwSchlüssel, netwSchlüsselLän );
		klient->sendeEncrypted( "\6\x8", 2 );
		char byte = 0;
		klient->getNachrichtEncrypted( &byte, 1 );
		if( byte == 2 )
		{
			unsigned char lsIp[ 4 ];
			klient->getNachrichtEncrypted( (char *)lsIp, 4 );
			unsigned short lsPort = 0;
			klient->getNachrichtEncrypted( (char*)&lsPort, 2 );
			klient->sendeEncrypted( "\3", 1 );
			klient->getNachrichtEncrypted( &serverReturn, 1 );
			klient->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 l = 0;
            char *key;
            Keys::getServerKey( &key, l, Keys::ERHALTUNG, Keys::SENDEN );
            klient->setSendeKey( key, l );
            delete[] key;
            Keys::getServerKey( &key, l, Keys::ERHALTUNG, Keys::EMPFANGEN );
            klient->setEmpfangKey( key, l );
            delete[] key;
			klient->verbinde( lsPort, lsIpT->getText() );
			lsIpT = lsIpT->release();
			klient->sende( "\0", 1 ); // Verschlüsselung aktivieren
			klient->sendeEncrypted( "\3", 1 );
			klient->getNachrichtEncrypted( &serverReturn, 1 );
			klient->trenne();
		}
		if( byte == 3 )
		{
			klient->getNachrichtEncrypted( &byte, 1 );
			char *f = new char[ byte + 1 ];
			f[ byte ] = 0;
			klient->getNachrichtEncrypted( f, byte );
			delete[]f;
			klient->sendeEncrypted( "\3", 1 );
			klient->getNachrichtEncrypted( &serverReturn, 1 );
			klient->trenne();
			klient = klient->release();
			return;
		}
	}
	if( klient->verbinde( klient->getServerPort(), klient->getServerIp() ) )
	{
		klient->sende( "\0", 1 ); // Verschlüsselung Aktivieren
		if( klient->sendeEncrypted( "\1", 1 ) )
		{
			klient->sendeEncrypted( (char*)&klientId, 4 );
			char serverReturn = 0;
			klient->getNachrichtEncrypted( &serverReturn, 1 );
			if( serverReturn == 3 )
			{
				char byte = 0;
				klient->getNachrichtEncrypted( &byte, 1 );
				char *f = new char[ byte + 1 ];
				f[ byte ] = 0;
				klient->getNachrichtEncrypted( f, byte );
				delete[]f;
				klient->sendeEncrypted( "\3", 1 );
				klient->getNachrichtEncrypted( &serverReturn, 1 );
				klient->trenne();
				return;
			}
			klient->setSendeKey( (char*)netwSchlüssel, netwSchlüsselLän );
			klient->setEmpfangKey( (char*)netwSchlüssel, netwSchlüsselLän );
			start();
		}
		else
			klient = klient->release();
	}
	else
		klient = klient->release();
}

void ErhaltungKlient::abmelden()
{
	abmel = 1;
}

void ErhaltungKlient::trennen()
{
	trenn = 1;
}

void ErhaltungKlient::thread()
{
	while( 1 )
	{
		char n = 0;
		klient->getNachrichtEncrypted( &n, 1 );
		if( n != 1 )
		{
			Sleep( 250 );
			continue;
		}
		if( trenn )
		{
			if( abmel )
			{
				klient->sendeEncrypted( "\1", 1 );
				klient->getNachrichtEncrypted( &n, 1 );
			}
			klient->trenne();
			run = 0;
			return;
		}
		else
			klient->sendeEncrypted( "\0", 1 );
	}
}

// constant

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

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