#include "MSKlient.h"

// Inhalt der MSKlient Klasse aus MSKlient.h
// Konstruktor
MSKlient::MSKlient( const char *ip, int port )
{
	k = new SSLKlient();
	fehler = new Text( "Keine Verbindung zum Server." );
	this->ip = new Text( ip );
	this->port = port;
	verbunden = 0;
	eingeloggt = 0;
	InitializeCriticalSection( &cs );
	ref = 1;
}

// Destruktor
MSKlient::~MSKlient()
{
	if( verbunden )
		trenne();
	k->release();
	ip->release();
	fehler->release();
	DeleteCriticalSection( &cs );
}

// nicht constant
void MSKlient::lock()
{
	EnterCriticalSection( &cs );
}

void MSKlient::unlock()
{
	LeaveCriticalSection( &cs );
}

bool MSKlient::verbinden()
{
	if( verbunden )
		return 1;
	lock();
	bool b = k->verbinde( port, ip->getText() );
	if( !b )
	{
		fehler->setText( "Fehler während verbinden bei MainServer.\nPort:" );
		fehler->append( port );
		fehler->append( " IP:" );
		fehler->append( ip->getText() );
	}
	verbunden = b;
	eingeloggt = 0;
	unlock();
	return b;
}

bool MSKlient::login( const char *name, const char *passwort )
{
	if( !verbunden )
		verbinden();
	if( !verbunden )
		return 0;
	lock();
	k->sende( "\1", 1 );
	unsigned char res = 0;
	k->getNachricht( (char*)&res, 1 );
	if( res == 1 )
	{
		unsigned char län = (unsigned char)textLength( name );
		k->sende( (char*)&län, 1 );
		if( län )
			k->sende( name, län );
		län = (unsigned char)textLength( passwort );
		k->sende( (char*)&län, 1 );
		if( län )
			k->sende( passwort, län );
		k->getNachricht( (char*)&res, 1 );
	}
	if( res == 3 )
	{
		k->getNachricht( (char*)&res, 1 );
		char *txt = new char[ res + 1 ];
		k->getNachricht( txt, res );
		txt[ res ] = 0;
		fehler->setText( "Fehler während einloggen bei MainServer.\nServer Rückgabe:" );
		fehler->append( txt );
		delete[] txt;
	}
	else
	{
		eingeloggt = 1;
		unlock();
		return 1;
	}
	unlock();
	return 0;
}

bool MSKlient::logout()
{
	if( !verbunden )
		verbinden();
	if( !verbunden )
		return 0;
	lock();
	k->sende( "\2", 1 );
	unsigned char res = 0;
	k->getNachricht( (char*)&res, 1 );
	if( res == 3 )
	{
		k->getNachricht( (char*)&res, 1 );
		char *txt = new char[ res + 1 ];
		k->getNachricht( txt, res );
		txt[ res ] = 0;
		fehler->setText( "Fehler während ausloggen bei MainServer.\nServer Rückgabe:" );
		fehler->append( txt );
		delete[] txt;
	}
	unlock();
	return res == 1;
}

int MSKlient::getStatus()
{
	if( !verbunden )
		verbinden();
	if( !verbunden )
		return -1;
	lock();
	k->sende( "\x8", 1 );
	unsigned char res = 0;
	k->getNachricht( (char*)&res, 1 );
	int status = 0;
	if( res == 1 )
	{
		k->getNachricht( (char*)&res, 1 );
		if( res == 1 )
			status = 1;
	}
	if( res == 3 )
	{
		status = -2;
		k->getNachricht( (char*)&res, 1 );
		char *txt = new char[ res + 1 ];
		k->getNachricht( txt, res );
		txt[ res ] = 0;
		fehler->setText( "Fehler während Status Request bei MainServer.\nServer Rückgabe:" );
		fehler->append( txt );
		delete[] txt;
	}
	unlock();
	return (int)res;
}

bool MSKlient::pause()
{
	if( !verbunden )
		verbinden();
	if( !verbunden )
		return 0;
	lock();
	k->sende( "\5", 1 );
	unsigned char res = 0;
	k->getNachricht( (char*)&res, 1 );
	if( res == 3 )
	{
		k->getNachricht( (char*)&res, 1 );
		char *txt = new char[ res + 1 ];
		k->getNachricht( txt, res );
		txt[ res ] = 0;
		fehler->setText( "Fehler während Pausieren bei MainServer.\nServer Rückgabe:" );
		fehler->append( txt );
		delete[] txt;
	}
	unlock();
	return res == 1;
}

bool MSKlient::fortsetzen()
{
	if( !verbunden )
		verbinden();
	if( !verbunden )
		return 0;
	lock();
	k->sende( "\4", 1 );
	unsigned char res = 0;
	k->getNachricht( (char*)&res, 1 );
	if( res == 3 )
	{
		k->getNachricht( (char*)&res, 1 );
		char *txt = new char[ res + 1 ];
		k->getNachricht( txt, res );
		txt[ res ] = 0;
		fehler->setText( "Fehler während Fortsetzen bei MainServer.\nServer Rückgabe:" );
		fehler->append( txt );
		delete[] txt;
	}
	unlock();
	return res == 1;
}

bool MSKlient::beenden()
{
	if( !verbunden )
		verbinden();
	if( !verbunden )
		return 0;
	lock();
	k->sende( "\6", 1 );
	unsigned char res = 0;
	k->getNachricht( (char*)&res, 1 );
	if( res == 3 )
	{
		k->getNachricht( (char*)&res, 1 );
		char *txt = new char[ res + 1 ];
		k->getNachricht( txt, res );
		txt[ res ] = 0;
		fehler->setText( "Fehler während Beenden bei MainServer.\nServer Rückgabe:" );
		fehler->append( txt );
		delete[] txt;
	}
	unlock();
	if( res == 1 )
	{
		eingeloggt = 0;
		verbunden = 0;
	}
	return res == 1;
}

bool MSKlient::terminieren()
{
	if( !verbunden )
		verbinden();
	if( !verbunden )
		return 0;
	lock();
	k->sende( "\7", 1 );
	unsigned char res = 0;
	k->getNachricht( (char*)&res, 1 );
	if( res == 3 )
	{
		k->getNachricht( (char*)&res, 1 );
		char *txt = new char[ res + 1 ];
		k->getNachricht( txt, res );
		txt[ res ] = 0;
		fehler->setText( "Fehler während Terminieren bei MainServer.\nServer Rückgabe:" );
		fehler->append( txt );
		delete[] txt;
	}
	unlock();
	if( res == 1 )
	{
		eingeloggt = 0;
		verbunden = 0;
	}
	return res == 1;
}

bool MSKlient::getPatchServerListe( Array< ServerData* > *list )
{
    if( !verbunden )
        verbinden();
    if( !verbunden )
        return 0;
    lock();
    k->sende( "\x9", 1 );
    unsigned char res = 0;
    k->getNachricht( (char*)&res, 1 );
    if( res == 3 )
    {
        k->getNachricht( (char*)&res, 1 );
        char *txt = new char[ res + 1 ];
        k->getNachricht( txt, res );
        txt[ res ] = 0;
        fehler->setText( "Fehler während Terminieren bei MainServer.\nServer Rückgabe:" );
        fehler->append( txt );
        delete[] txt;
        unlock();
        return 0;
    }
    else if( res == 1 )
    {
        int anz = 0;
        k->getNachricht( (char*)&anz, 4 );
        for( int i = 0; i < anz; i++ )
        {
            ServerData *s = new ServerData();
            k->getNachricht( (char*)&s->id, 4 );
            k->getNachricht( (char*)&s->port, 2 );
            k->getNachricht( (char*)&s->adminPort, 2 );
            unsigned char len = 0;
            k->getNachricht( (char*)&len, 1 );
            s->name.fillText( ' ', len );
            k->getNachricht( s->name, len );
            k->getNachricht( (char*)&len, 1 );
            s->ip.fillText( ' ', len );
            k->getNachricht( s->ip, len );
            k->getNachricht( (char*)&len, 1 );
            s->status.fillText( ' ', len );
            k->getNachricht( s->status, len );
            list->add( s );
        }
    }
    unlock();
    return 1;
}

bool MSKlient::getPatchServerDetails( int id, ServerDetails *details )
{
    if( !verbunden )
        verbinden();
    if( !verbunden )
        return 0;
    lock();
    k->sende( "\xA", 1 );
    unsigned char res = 0;
    k->getNachricht( (char*)&res, 1 );
    if( res == 1 )
    {
        k->sende( (char*)&id, 4 );
        k->getNachricht( (char*)&res, 1 );
        if( res == 1 )
        {
            unsigned char len = 0;
            k->getNachricht( (char*)&len, 1 );
            details->name.fillText( ' ', len );
            k->getNachricht( details->name, len );
            k->getNachricht( (char*)&len, 1 );
            details->ip.fillText( ' ', len );
            k->getNachricht( details->ip, len );
            k->getNachricht( (char*)&details->port, 2 );
            k->getNachricht( (char*)&details->adminPort, 2 );
            k->getNachricht( (char*)&details->tasks, 4 );
            k->getNachricht( (char*)&details->maxTasks, 4 );
        }
    }
    if( res == 3 )
    {
        k->getNachricht( (char*)&res, 1 );
        char *txt = new char[ res + 1 ];
        k->getNachricht( txt, res );
        txt[ res ] = 0;
        fehler->setText( "Fehler während Terminieren bei MainServer.\nServer Rückgabe:" );
        fehler->append( txt );
        delete[] txt;
        unlock();
        return 0;
    }
    unlock();
    return 1;
}

bool MSKlient::trenne()
{
	if( !verbunden )
		verbinden();
	if( !verbunden )
		return 0;
	lock();
	k->sende( "\3", 1 );
	unsigned char res = 0;
	k->getNachricht( (char*)&res, 1 );
	if( res == 3 )
	{
		k->getNachricht( (char*)&res, 1 );
		char *txt = new char[ res + 1 ];
		k->getNachricht( txt, res );
		txt[ res ] = 0;
		fehler->setText( "Fehler während Trennen bei MainServer.\nServer Rückgabe:" );
		fehler->append( txt );
		delete[] txt;
	}
	unlock();
	eingeloggt = 0;
	verbunden = 0;
	k->trenne();
	return res == 1;
}

// constant
bool MSKlient::istVerbunden() const
{
	return verbunden;
}

bool MSKlient::istEingeloggt() const
{
	return eingeloggt;
}

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

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

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