#include <Klient.h>
#include <main.h>
#include <Fenster.h>
#include <Text.h>
#include <Datei.h>
#include <Punkt.h>
#include <Bildschirm.h>
#include <Prozess.h>
#include <Knopf.h>
#include <Bild.h>
#include <DateiSystem.h>
#include <MausEreignis.h>
#include <TastaturEreignis.h>
#include <Fortschritt.h>
#include <Schrift.h>
#include <Liste.h>
#include <Rahmen.h>
#include <AlphaFeld.h>
#include <TextFeld.h>
#include <Maus.h>
#include <Zeit.h>
#include <InitDatei.h>
#include <Tabelle.h>
#include <Scroll.h>
#include <AuswahlBox.h>
#include <KSGTDatei.h>
#include <Globals.h>
#include "Patcher.h"
#include "News.h"

using namespace Framework;
using namespace Network;

bool _exitB = 0;
WFenster *_frame;
FBalken *_fortschritt;
TextFeld *_aktion;
TextFeld *_kbps;
Knopf *_play;
Patcher *_patcher;
Fenster *_optionenF;
ObjTabelle *_o_rt;
Knopf *_o_rno;
Knopf *_o_rnu;
TextFeld *_o_ülps;
AuswahlBox *_o_üle;

bool _newWechsel = 1;
bool _abbruch = 0;

bool _o_rkkME( void *p, void *obj, MausEreignis me );

void _frameSchließen( void *p, void *obj )
{

}

bool _frameME( void *p, void *obj, MausEreignis me )
{
	return 1;
}

bool _frameTE( void *p, void *obj, TastaturEreignis me )
{
	return 1;
}

bool closeME( void *p, void *obj, MausEreignis me )
{
	if( me.id == ME_RLinks )
	{
		_abbruch = 1;
		PostQuitMessage( 0 );
	}
	return 1;
}

bool minimierenME( void *p, void *obj, MausEreignis me )
{
	if( me.id == ME_RLinks )
	{
		_frame->setAnzeigeModus( 2 );
	}
	return 1;
}

bool _playME( void *p, void *obj, MausEreignis me )
{
	if( me.id == ME_Betritt )
		getMaus().ladeMaus( MausId::hand );
	if( me.id == ME_Leaves )
        getMaus().ladeMaus( MausId::normal );
    getMaus().update();
	if( me.id == ME_RLinks )
		PostQuitMessage( 0 );
	return 1;
}

bool optionenME( void *p, void *obj, MausEreignis me )
{
	if( me.id == ME_RLinks )
	{
        _o_rno->removeStyle( Knopf::Style::Erlaubt );
        _o_rnu->removeStyle( Knopf::Style::Erlaubt );
		while( _o_rt->getZeilenAnzahl() > 1 )
		{
			if( _o_rt->zZeichnung( 0, 1 ) )
				( (TextFeld*)_o_rt->zZeichnung( 0, 1 ) )->release();
			if( _o_rt->zZeichnung( 1, 1 ) )
				( (KontrollKnopf*)_o_rt->zZeichnung( 1, 1 ) )->release();
			_o_rt->removeZeile( 1 );
		}
		KSGTDatei *dat = new KSGTDatei( "data/dg.ksgt" ); // Tabellen Spalten: Id, Pfad, Version, Priorität
		dat->laden();
		int max = -1;
		for( int i = 0; i < dat->getZeilenAnzahl(); i++ )
		{
			if( !dat->zFeld( i, 3 ) || dat->zFeld( i, 3 )->istGleich( "NICHT" ) || dat->zFeld( i, 3 )->istGleich( "" ) )
				continue;
			if( max < (int)TextZuInt( dat->zFeld( i, 3 )->getText(), 10 ) )
				max = (int)TextZuInt( dat->zFeld( i, 3 )->getText(), 10 );
		}
		for( int i = 0; i <= max; i++ )
		{
			for( int j = 0; j < dat->getZeilenAnzahl(); j++ )
			{
				if( !dat->zFeld( j, 1 ) || dat->zFeld( j, 1 )->istGleich( "" ) )
					continue;
				Text *iT = new Text( "" );
				iT->append( i );
				if( dat->zFeld( j, 3 ) && dat->zFeld( j, 3 )->istGleich( iT ) )
				{
					Text *name = dat->zFeld( j, 1 )->getTeilText( dat->zFeld( j, 1 )->positionVon( "spiele/" ) + 7 );
					if( !name || !name->getLength() || !dat->zFeld( j, 1 )->hat( "spiele/" ) )
					{
						if( name )
							name->release();
						name = dat->zFeld( j, 1 )->getTeilText( dat->zFeld( j, 1 )->positionVon( "Spiele/" ) + 7 );
					}
					if( !name || !name->getLength() || ( !dat->zFeld( j, 1 )->hat( "Spiele/" ) && !dat->zFeld( j, 1 )->hat( "spiele/" ) ) )
					{
						if( name )
							name->release();
						name = new Text( dat->zFeld( j, 1 )->getText() );
						if( name->hat( '/' ) )
							name->remove( 0, name->positionVon( '/', name->anzahlVon( '/' ) - 1 ) + 1 );
					}
					int anz = _o_rt->getZeilenAnzahl();
					_o_rt->addZeile( dat->zFeld( j, 0 )->getText() );
					Text *spielN = 0;
					if( name->positionVon( '/' ) >= 0 )
						spielN = name->getTeilText( 0, name->positionVon( '/' ) );
					else
						spielN = new Text( name->getText() );
					name = name->release();
					TextFeld *spiel = new TextFeld();
					spiel->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
					spiel->setSchriftZ( _optionenF->getTSchrift() );
					spiel->setSchriftFarbe( 0xFFFFFFFF );
					spiel->setHintergrundFarbe( 0xFF003000 );
					spiel->setText( spielN );
					_o_rt->setZeichnungZ( 0, anz, spiel );
					KontrollKnopf *erlaubt = new KontrollKnopf();
					erlaubt->addStyle( KontrollKnopf::Style::Sichtbar | KontrollKnopf::Style::Erlaubt | KontrollKnopf::Style::KlickBuffer | KontrollKnopf::Style::Selected );
					erlaubt->setHintergrundFarbe( 0xFF003000 );
					erlaubt->setSBgFarbe( 0xFF003000 );
					erlaubt->loadData( "data/bilder/system.ltdb" );
					erlaubt->setMausEreignis( _o_rkkME );
					_o_rt->setZeichnungZ( 1, anz, erlaubt );
				}
			}
		}
		for( int i = 0; i < dat->getZeilenAnzahl(); i++ )
		{
			if( dat->zFeld( i, 3 ) && dat->zFeld( i, 3 )->istGleich( "NICHT" ) )
			{
				Text *name = dat->zFeld( i, 1 )->getTeilText( dat->zFeld( i, 1 )->positionVon( "spiele/" ) + 7 );
				if( !name || !name->getLength() )
				{
					if( name )
						name->release();
					name = dat->zFeld( i, 1 )->getTeilText( dat->zFeld( i, 1 )->positionVon( "Spiele/" ) + 7 );
				}
				if( !name || !name->getLength() )
				{
					if( name )
						name->release();
					name = new Text( dat->zFeld( i, 1 )->getText() );
					if( name->hat( '/' ) )
						name->remove( 0, name->positionVon( '/', name->anzahlVon( '/' ) - 1 ) );
				}
				int anz = _o_rt->getZeilenAnzahl();
				_o_rt->addZeile( dat->zFeld( i, 0 )->getText() );
				Text *spielN = 0;
				if( name->positionVon( '/' ) >= 0 )
					spielN = name->getTeilText( 0, name->positionVon( '/' ) );
				else
					spielN = new Text( name->getText() );
				name = name->release();
				TextFeld *spiel = new TextFeld();
				spiel->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
				spiel->setSchriftZ( _optionenF->getTSchrift() );
				spiel->setSchriftFarbe( 0xFFFFFFFF );
				spiel->setHintergrundFarbe( 0xFF003000 );
				spiel->setText( spielN );
				_o_rt->setZeichnungZ( 0, anz, spiel );
				KontrollKnopf *erlaubt = new KontrollKnopf();
				erlaubt->addStyle( KontrollKnopf::Style::Sichtbar | KontrollKnopf::Style::Erlaubt | KontrollKnopf::Style::KlickBuffer );
				erlaubt->setHintergrundFarbe( 0xFF003000 );
				erlaubt->loadData( "data/bilder/system.ltdb" );
				erlaubt->setMausEreignis( _o_rkkME );
				_o_rt->setZeichnungZ( 1, anz, erlaubt );
			}
		}
		dat->release();
		InitDatei *ini = new InitDatei( "data/patch/po.ini" );
		ini->laden();
		if( ini->wertExistiert( "ülps" ) )
			_o_ülps->setText( ini->zWert( "ülps" )->getText() );
		if( ini->wertExistiert( "üle" ) )
			_o_üle->setAuswahl( _o_üle->getEintragPos( ini->zWert( "üle" )->getThis() ) );
		ini->release();
		_optionenF->setPosition( 100, 100 );
		_optionenF->addStyle( Fenster::Style::Sichtbar );
	}
	return 1;
}

bool oAbbrechen( void *p, void *obj, MausEreignis me )
{
	if( me.id == ME_RLinks )
		_optionenF->removeStyle( Fenster::Style::Sichtbar );
	return 1;
}

bool _o_rtME( void *p, void *obj, MausEreignis me )
{
	if( me.id == ME_RLinks )
	{
		for( int i = 1; i < _o_rt->getZeilenAnzahl(); i++ )
		{
			if( _o_rt->zZeichnung( 0, i ) )
				( (TextFeld*)_o_rt->zZeichnung( 0, i ) )->removeStyle( TextFeld::Style::Hintergrund );
			if( _o_rt->zZeichnung( 1, i ) )
				( (KontrollKnopf*)_o_rt->zZeichnung( 1, i ) )->removeStyle( KontrollKnopf::Style::Hintergrund | KontrollKnopf::Style::SelectFarbe );
		}
		int zeile = (int)_o_rt->getMausZeile( me.my - _o_rt->getY() - _o_rt->getVertikalScrollPos() );
		if( zeile <= 0 )
		{
			_o_rno->removeStyle( Knopf::Style::Erlaubt );
			_o_rnu->removeStyle( Knopf::Style::Erlaubt );
		}
		else
		{
			if( _o_rt->zZeichnung( 0, zeile ) )
				( (TextFeld*)_o_rt->zZeichnung( 0, zeile ) )->addStyle( TextFeld::Style::Hintergrund );
			if( _o_rt->zZeichnung( 1, zeile ) )
				( (KontrollKnopf*)_o_rt->zZeichnung( 1, zeile ) )->addStyle( KontrollKnopf::Style::Hintergrund | KontrollKnopf::Style::SelectFarbe );
			if( zeile > 1 )
				_o_rno->addStyle( Knopf::Style::Erlaubt );
			else
				_o_rno->removeStyle( Knopf::Style::Erlaubt );
			int max = 0;
			for( int i = 1; i < _o_rt->getZeilenAnzahl(); i++ )
			{
				if( !_o_rt->zZeichnung( 1, i ) || ( (KontrollKnopf*)_o_rt->zZeichnung( 1, i ) )->hatStyleNicht( KontrollKnopf::Style::Selected ) )
					break;
				max = i;
			}
			if( zeile < max )
				_o_rnu->addStyle( Knopf::Style::Erlaubt );
			else
				_o_rnu->removeStyle( Knopf::Style::Erlaubt );
			if( ( _o_rt->zZeichnung( 1, zeile ) && ( (KontrollKnopf*)_o_rt->zZeichnung( 1, zeile ) )->hatStyleNicht( KontrollKnopf::Style::Selected ) ) )
			{
				_o_rno->removeStyle( Knopf::Style::Erlaubt );
				_o_rnu->removeStyle( Knopf::Style::Erlaubt );
			}
		}
	}
	return 1;
}

bool _o_rnoME( void *p, void *obj, MausEreignis me )
{
	if( me.id == ME_RLinks )
	{
		int zeile = -1;
		for( int i = 1; i < _o_rt->getZeilenAnzahl(); i++ )
		{
			if( _o_rt->zZeichnung( 0, i ) && ( (TextFeld*)_o_rt->zZeichnung( 0, i ) )->hatStyle( TextFeld::Style::Hintergrund ) )
			{
				zeile = i;
				break;
			}
		}
		if( zeile > 1 )
		{
			_o_rt->setZeilePosition( zeile, zeile - 1 );
			_o_rnu->addStyle( Knopf::Style::Erlaubt );
		}
		if( zeile - 1 <= 1 )
			_o_rno->removeStyle( Knopf::Style::Erlaubt );
	}
	return 1;
}

bool _o_rnuME( void *p, void *obj, MausEreignis me )
{
	if( me.id == ME_RLinks )
	{
		int zeile = -1;
		for( int i = 1; i < _o_rt->getZeilenAnzahl(); i++ )
		{
			if( _o_rt->zZeichnung( 0, i ) && ( (TextFeld*)_o_rt->zZeichnung( 0, i ) )->hatStyle( TextFeld::Style::Hintergrund ) )
			{
				zeile = i;
				break;
			}
		}
		int max = 0;
		for( int i = 1; i < _o_rt->getZeilenAnzahl(); i++ )
		{
			if( !_o_rt->zZeichnung( 1, i ) || ( (KontrollKnopf*)_o_rt->zZeichnung( 1, i ) )->hatStyleNicht( KontrollKnopf::Style::Selected ) )
				break;
			max = i;
		}
		if( zeile > 0 && zeile < max )
		{
			_o_rt->setZeilePosition( zeile, zeile + 1 );
			_o_rno->addStyle( Knopf::Style::Erlaubt );
		}
		if( zeile + 1 >= _o_rt->getZeilenAnzahl() - 1 )
			_o_rnu->removeStyle( Knopf::Style::Erlaubt );
	}
	return 1;
}

bool _o_rkkME( void *p, void *obj, MausEreignis me )
{
	if( me.id == ME_RLinks )
	{
		if( ( (KontrollKnopf*)obj )->hatStyleNicht( KontrollKnopf::Style::Hintergrund | KontrollKnopf::Style::SelectFarbe ) )
		{
			( (KontrollKnopf*)obj )->setStyle( KontrollKnopf::Style::Selected, ( (KontrollKnopf*)obj )->hatStyleNicht( KontrollKnopf::Style::Selected ) );
			return 1;
		}
		if( ( (KontrollKnopf*)obj )->hatStyle( KontrollKnopf::Style::Selected ) )
		{
			_o_rno->removeStyle( Knopf::Style::Erlaubt );
			_o_rnu->removeStyle( Knopf::Style::Erlaubt );
			int zeile = -1;
			for( int i = 1; i < _o_rt->getZeilenAnzahl(); i++ )
			{
				if( _o_rt->zZeichnung( 1, i ) == obj )
				{
					zeile = i;
					break;
				}
			}
			int max = 0;
			for( int i = 1; i < _o_rt->getZeilenAnzahl(); i++ )
			{
				if( !_o_rt->zZeichnung( 1, i ) || ( (KontrollKnopf*)_o_rt->zZeichnung( 1, i ) )->hatStyleNicht( KontrollKnopf::Style::Selected ) )
					break;
				max = i;
			}
			_o_rt->setZeilePosition( zeile, max );
		}
		else
		{
			int zeile = -1;
			for( int i = 1; i < _o_rt->getZeilenAnzahl(); i++ )
			{
				if( _o_rt->zZeichnung( 1, i ) == obj )
				{
					zeile = i;
					break;
				}
			}
			int max = 0;
			for( int i = 1; i < _o_rt->getZeilenAnzahl(); i++ )
			{
				if( !_o_rt->zZeichnung( 1, i ) || ( (KontrollKnopf*)_o_rt->zZeichnung( 1, i ) )->hatStyleNicht( KontrollKnopf::Style::Selected ) )
					break;
				max = i;
			}
			_o_rt->setZeilePosition( zeile, max + 1 );
			if( max > 1 )
				_o_rno->addStyle( Knopf::Style::Erlaubt );
		}
	}
	return 1;
}

bool _o_ülpsTE( void *p, void *obj, TastaturEreignis te )
{
	if( te.taste == T_Links || te.taste == T_Rechts || te.taste == T_Entf || te.taste == T_BackSpace || ( te.taste >= '0' && te.taste <= '9' ) )
		return 1;
	return 0;
}

bool o_okME( void *p, void *obj, MausEreignis me )
{
	if( me.id == ME_RLinks )
	{
		KSGTDatei *dat = new KSGTDatei( "data/dg.ksgt" );
		dat->laden();
		for( int i = 0; i < dat->getZeilenAnzahl(); i++ )
		{
			for( int j = 0; j < _o_rt->getZeilenAnzahl(); j++ )
			{
				if( !_o_rt->zZeichnung( 1, j ) )
					continue;
				if( !_o_rt->zZeilenName( j )->istGleich( dat->zFeld( i, 0 )->getText() ) )
					continue;
				if( ( (KontrollKnopf*)_o_rt->zZeichnung( 1, j ) )->hatStyle( KontrollKnopf::Style::Selected ) )
				{
					Text *t = new Text();
					t->append( j );
					dat->zFeld( i, 3 )->setText( t );
				}
				else
					dat->zFeld( i, 3 )->setText( "NICHT" );
				break;
			}
		}
		dat->speichern();
		dat->release();
		InitDatei *ini = new InitDatei( "data/patch/po.ini" );
		ini->addWert( "ülps", _o_ülps->zText()->getText() );
		ini->addWert( "üle", _o_üle->zEintragText( _o_üle->getAuswahl() )->getText() );
		ini->speichern();
		ini->release();
		_optionenF->removeStyle( Fenster::Style::Sichtbar );
	}
	return 1;
}

DWORD WINAPI runThread( void *args )
{
	Bildschirm *screen = (Bildschirm *)args;
	double i = 0;
	double tickVal = 1.0 / 60.0;
	ZeitMesser *tstop = new ZeitMesser();
	while( !_exitB )
	{
		tstop->messungStart();
		screen->render();
		screen->tick( tickVal );
		Sleep( 10 );
		if( _kbps )
		{
			i += tickVal * 60;
			if( i >= 60 && _kbps )
			{
				screen->lock();
				_kbps->setText( "" );
				_kbps->zText()->append( _patcher ? ( _patcher->getDownload() / 1024 ) : 0 );
				_kbps->zText()->append( " kb/s, " );
				_kbps->zText()->append( (unsigned int)( ( _fortschritt->getAktionAnzahl() - _fortschritt->getAktion() ) / 1024 ) );
				_kbps->zText()->append( " kb verbleibend..." );
				screen->unlock();
				i -= 60;
			}
		}
		tstop->messungEnde();
		tickVal = tstop->getSekunden() + tstop->getSekunden() - tickVal;
	}
	tstop->release();
	return 0;
}

int KSGStart Framework::Start( Startparam p )
{
	_abbruch = 0;
	Network::Start( 10 );

	LTDBDatei *patcherBilder = new LTDBDatei();
	patcherBilder->setDatei( new Text( "data/patch/bilder/patcher.ltdb" ) );
	patcherBilder->leseDaten( 0 );
	Bild *patcherRahmen = patcherBilder->laden( 0, new Text( "patcherrahmen." ) );
	Bild *patcherHintergrund = patcherBilder->laden( 0, new Text( "patcher.png" ) );
	Bild *playBild = patcherBilder->laden( 0, new Text( "play.png" ) );
	Bild *playKlick = patcherBilder->laden( 0, new Text( "playklick.png" ) );
	patcherBilder->release();

	LTDBDatei *systemBilder = new LTDBDatei();
	systemBilder->setDatei( new Text( "data/bilder/system.ltdb" ) );
	systemBilder->leseDaten( 0 );
	Bild *systemSchließen = systemBilder->laden( 0, new Text( "schließen.png" ) );
	Bild *systemMinimieren = systemBilder->laden( 0, new Text( "minimieren.png" ) );
	Bild *systemOptionen = systemBilder->laden( 0, new Text( "optionen.png" ) );
	Bild *systemFortschrittL = systemBilder->laden( 0, new Text( "fortschrittleh" ) );
	Bild *systemFortschrittV = systemBilder->laden( 0, new Text( "fortschrittvol" ) );
	systemBilder->release();

	LTDSDatei *normalSchrift = new LTDSDatei();
	normalSchrift->setPfad( new Text( "data/schriften/normal.ltds" ) );
	normalSchrift->leseDaten();
	Schrift *sNormal = normalSchrift->ladeSchrift();
	normalSchrift->release();

	WNDCLASS wc = F_Normal( p.hinst );
	wc.lpszClassName = "Kolja-Strohm Games Patcher";
	_frame = new WFenster();
	_frame->setVerschiebbar( 1 );
	_frame->erstellen( WS_POPUP, wc );
	_frame->setSize( Punkt( 500, 500 ) );
	_frame->setPosition( Bildschirmmitte( _frame->getThis() ) );
	_frame->ladeRahmenFenster( patcherRahmen, p.hinst );
	_frame->setMausAktion( _frameME );
	_frame->setTastaturAktion( _frameTE );
	_frame->setVSchließAktion( _frameSchließen );
	Bildschirm *screen = new Bildschirm3D( _frame->getThis() );
	screen->update();
	screen->render();
	_frame->setBildschirm( screen->getThis() );
	_frame->setAnzeigeModus( 1 );

	screen->lock();
	BildZ *hintergrund = new BildZ();
	hintergrund->setStyle( BildZ::Style::Sichtbar );
	hintergrund->setBildZ( patcherHintergrund->getThis() );
	hintergrund->setPosition( 0, 0 );
	hintergrund->setSize( patcherHintergrund->getBreite(), patcherHintergrund->getHeight() );
	screen->addMember( hintergrund );

	Knopf *close = new Knopf();
	close->setStyle( Knopf::Style::Sichtbar | Knopf::Style::Erlaubt | Knopf::Style::Hintergrund | Knopf::Style::HAlpha | Knopf::Style::HBild | Knopf::Style::KlickBuffer );
	close->setHintergrundBildZ( systemSchließen->getThis() );
	close->setKBFarbe( 0xFF000000 );
    close->setHintergrundFarbe( 0 );
	close->setKBStrength( 30 );
	close->setPosition( 475, 5 );
	close->setSize( 20, 20 );
	close->setMausEreignis( closeME );
	screen->addMember( close );

	Knopf *minimieren = new Knopf();
	minimieren->setStyle( Knopf::Style::Sichtbar | Knopf::Style::Erlaubt | Knopf::Style::Hintergrund | Knopf::Style::HAlpha | Knopf::Style::HBild | Knopf::Style::KlickBuffer );
	minimieren->setHintergrundBildZ( systemMinimieren->getThis() );
    minimieren->setHintergrundFarbe( 0 );
	minimieren->setKBFarbe( 0xFF000000 );
	minimieren->setKBStrength( 30 );
	minimieren->setPosition( 454, 5 );
	minimieren->setSize( 20, 20 );
	minimieren->setMausEreignis( minimierenME );
	screen->addMember( minimieren );

	Knopf *optionen = new Knopf();
	optionen->setStyle( Knopf::Style::Sichtbar | Knopf::Style::Erlaubt | Knopf::Style::Hintergrund | Knopf::Style::HAlpha | Knopf::Style::HBild | Knopf::Style::KlickBuffer );
	optionen->setHintergrundBildZ( systemOptionen->getThis() );
    optionen->setHintergrundFarbe( 0 );
	optionen->setKBFarbe( 0xFF000000 );
	optionen->setKBStrength( 30 );
	optionen->setPosition( 433, 5 );
	optionen->setSize( 20, 20 );
	optionen->setMausEreignis( optionenME );
	screen->addMember( optionen );

    // Main Server Adresse Laden
    Datei *dat = new Datei();
    dat->setDatei( "data/tmp/k.id" );
    int klientNummer = 0;
    dat->open( Datei::Style::lesen );
    dat->lese( (char*)&klientNummer, 4 );
    dat->close();
    dat->setDatei( "data/tmp/m.port" );
    int serverPort = 0;
    dat->open( Datei::Style::lesen );
    dat->lese( (char*)&serverPort, 4 );
    dat->close();
    dat->setDatei( "data/tmp/m.ip" );
    dat->open( Datei::Style::lesen );
    unsigned char len = 0;
    dat->lese( (char*)&len, 1 );
    char *ip = new char[ len + 1 ];
    ip[ len ] = 0;
    dat->lese( ip, len );
    dat->close();
    dat->setDatei( "data/tmp/crypt.key" );
    dat->open( Datei::Style::lesen );
    len = 0;
    dat->lese( (char*)&len, 1 );
    char *key = new char[ len + 1 ];
    key[ len ] = 0;
    dat->lese( key, len );
    dat->close();
    dat->release();

    // Laden des Main Clients
    HINSTANCE networkDLL = LoadLibrary( "data/bin/KSGNetwork.dll" );
    if( !networkDLL )
    {
        WMessageBox( 0, new Text( "Fehler" ), new Text( "Die DLL Datei 'data/bin/KSGNetwork.dll' konnte nicht geladen werden. Fallst diese Datei nicht existiert muss das Spiel neu Installiert werden." ), MB_ICONERROR );
        exit( 0 );
    }
    KSGClient::KSGNetworkCreateRegisterdMain getMainClient = ( KSGClient::KSGNetworkCreateRegisterdMain )GetProcAddress( networkDLL, KSGNETWORK_CREATE_REGISTERD_MAIN );
    if( !getMainClient )
    {
        WMessageBox( 0, new Text( "Fehler" ), new Text( "Der Einstiegspunkt '" KSGNETWORK_CREATE_REGISTERD_MAIN "' wurde in der DLL Datei 'data/bin/KSGNetwork.dll' nicht gefunden. Fallst dieses Problem weiterhin auftritt muss das Spiel neu Installiert werden." ), MB_ICONERROR );
        exit( 0 );
    }
    KSGClient::MainServerClient *mainClient = getMainClient( ip, serverPort, klientNummer, key, len );
    if( !mainClient )
    {
        WMessageBox( 0, new Text( "Fehler" ), new Text( "Die DLL Datei 'data/bin/KSGNetwork.dll' scheint fehlerhaft zu sein. Fallst dieses Problem weiterhin auftritt muss das Spiel neu Installiert werden." ), MB_ICONERROR );
        exit( 0 );
    }

    delete[] ip;
    delete[] key;

	News *news = new News( screen, sNormal, mainClient->createNewsServerClient() );

	_aktion = new TextFeld();
	_aktion->setStyle( TextFeld::Style::Sichtbar );
	_aktion->setSchriftZ( sNormal->getThis() );
	_aktion->setSchriftFarbe( 0xFFFFFFFF );
	_aktion->setText( "Ermittle änderungen..." );
	_aktion->setPosition( 49, 403 );
	_aktion->setSize( 502, 20 );
	screen->addMember( _aktion );

	_kbps = new TextFeld();
	_kbps->setStyle( TextFeld::Style::Sichtbar );
	_kbps->setSchriftZ( sNormal->getThis() );
	_kbps->setSchriftFarbe( 0xFFFFFFFF );
	_kbps->setText( "0 kb/s" );
	_kbps->setPosition( 49, 460 );
	_kbps->setSize( 402, 20 );
	screen->addMember( _kbps );

	_fortschritt = new FBalken();
	_fortschritt->setStyle( FBalken::Style::Sichtbar | FBalken::Style::Hintergrund | FBalken::Style::HBild | FBalken::Style::FBild | FBalken::Style::Rahmen | FBalken::Style::Prozent | FBalken::Style::L_R );
	_fortschritt->setRahmenFarbe( 0xFFFFFFFF );
	_fortschritt->setHintergrundBild( systemFortschrittL->getThis() );
	_fortschritt->setFBgBild( systemFortschrittV->getThis() );
	_fortschritt->setSchriftZ( sNormal->getThis() );
	_fortschritt->setSFarbe( 0xFFFFFFFF );
	_fortschritt->setSSize( 12 );
	_fortschritt->setPosition( 49, 428 );
	_fortschritt->setSize( 402, 22 );
	screen->addMember( _fortschritt );

	_play = new Knopf();
	_play->setStyle( Knopf::Style::Erlaubt | Knopf::Style::Hintergrund | Knopf::Style::HBild | Knopf::Style::KlickBild );
	_play->setMausEreignis( _playME );
	_play->setHintergrundBildZ( playBild->getThis() );
	_play->setKlickBildZ( playKlick->getThis() );
	_play->setPosition( 200, 466 );
	_play->setSize( 101, 30 );
	screen->addMember( _play );

	_optionenF = new Fenster();
	_optionenF->setStyle( Fenster::Style::Erlaubt | Fenster::Style::Closable | Fenster::Style::Titel | Fenster::Style::TitelBuffered |
						  Fenster::Style::TitelHintergrund | Fenster::Style::BodyHintergrund | Fenster::Style::TitelHAlpha |
						  Fenster::Style::BodyHAlpha | Fenster::Style::Rahmen | Fenster::Style::ClosingKlickBuffer |
						  Fenster::Style::ClosingHintergrund | Fenster::Style::ClosingHAlpha | Fenster::Style::Beweglich | Fenster::Style::VScroll );
	_optionenF->setSize( 300, 300 );
	_optionenF->setPosition( 100, 100 );
	_optionenF->setVSBMax( 300 );
	_optionenF->zVScrollBar()->setKlickScroll( 10 );
	_optionenF->zVScrollBar()->setFarbe( 0xFFFFFFFF );
	_optionenF->zVScrollBar()->setBgFarbe( 0xF0000000, 1 );
	_optionenF->setRBreite( 2 );
	_optionenF->setRFarbe( 0xFFFFFFFF );
	_optionenF->setTSchriftZ( sNormal->getThis() );
	_optionenF->zTTextFeld()->addStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
	_optionenF->setTitel( "Optionen" );
	_optionenF->zTTextFeld()->setSize( 0, 20 );
	_optionenF->setTBgFarbe( 0xF0000000 );
	_optionenF->setTAfFarbe( 0xA0FFFFFF );
	_optionenF->setTAfStrength( 15 );
	_optionenF->setTSFarbe( 0xFFFFFFFF );
	_optionenF->setSBgFarbe( 0xF0000000 );
	_optionenF->setSKAfFarbe( 0xFFFFFFFF );
	_optionenF->setSKAfStrength( 30 );
	_optionenF->setKBgFarbe( 0xF0000000 );
	_optionenF->setClosingMe( oAbbrechen );
	screen->addMember( _optionenF );

	TextFeld *oReihenfolge = new TextFeld();
	oReihenfolge->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::VCenter );
	oReihenfolge->setSchriftZ( sNormal->getThis() );
	oReihenfolge->setSchriftFarbe( 0xFFFFFFFF );
	oReihenfolge->setText( "Update Reihenfolge:" );
	oReihenfolge->setPosition( 2, 2 );
	oReihenfolge->setSize( 276, 20 );
	_optionenF->addMember( oReihenfolge );

	_o_rt = new ObjTabelle();
	_o_rt->setStyle( ObjTabelle::Style::Sichtbar | ObjTabelle::Style::Erlaubt | ObjTabelle::Style::Rahmen | 
                     ObjTabelle::Style::Raster | ObjTabelle::Style::VScroll );
	_o_rt->setPosition( 2, 24 );
	_o_rt->setSize( 276, 150 );
	_o_rt->setRahmenBreite( 1 );
	_o_rt->setRahmenFarbe( 0xFFFFFFFF );
	_o_rt->setRasterBreite( 1 );
	_o_rt->setRasterFarbe( 0xFFFFFFFF );
	_o_rt->setVertikalKlickScroll( 10 );
	_o_rt->setMausEreignis( _o_rtME );
	_o_rt->addSpalte( "Spiel" );
	_o_rt->addSpalte( "Erlaubt" );
	_o_rt->setSpaltenBreite( 0, 237 );
	_o_rt->setSpaltenBreite( 1, 20 );
	_o_rt->addZeile( "Überschrift" );
	_o_rt->setZeilenHeight( 0, 15 );
	TextFeld *ortSpielT = new TextFeld();
	ortSpielT->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
	ortSpielT->setSchriftZ( sNormal->getThis() );
	ortSpielT->setSchriftFarbe( 0xFFFFFFFF );
	ortSpielT->setText( "Spiel" );
	_o_rt->setZeichnungZ( 0, 0, ortSpielT );
	_optionenF->addMember( _o_rt );

	_o_rno = new Knopf();
	_o_rno->setStyle( Knopf::Style::Sichtbar | Knopf::Style::Buffered | Knopf::Style::KlickBuffer | Knopf::Style::Rahmen );
	_o_rno->setPosition( 76, 176 );
	_o_rno->setSize( 100, 20 );
	_o_rno->setText( "nach Oben" );
	_o_rno->setSchriftZ( sNormal->getThis() );
	_o_rno->setMausEreignis( _o_rnoME );
	_optionenF->addMember( _o_rno );

	_o_rnu = new Knopf();
	_o_rnu->setStyle( Knopf::Style::Sichtbar | Knopf::Style::Buffered | Knopf::Style::KlickBuffer | Knopf::Style::Rahmen );
	_o_rnu->setPosition( 178, 176 );
	_o_rnu->setSize( 100, 20 );
	_o_rnu->setText( "nach Unten" );
	_o_rnu->setSchriftZ( sNormal->getThis() );
	_o_rnu->setMausEreignis( _o_rnuME );
	_optionenF->addMember( _o_rnu );

	TextFeld *oLimit = new TextFeld();
	oLimit->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::VCenter );
	oLimit->setSchriftZ( sNormal->getThis() );
	oLimit->setSchriftFarbe( 0xFFFFFFFF );
	oLimit->setText( "Übertragungslimit pro Sekunde:" );
	oLimit->setPosition( 2, 200 );
	oLimit->setSize( 276, 20 );
	_optionenF->addMember( oLimit );

	_o_ülps = new TextFeld();
	_o_ülps->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Erlaubt | TextFeld::Style::Rahmen | TextFeld::Style::Buffered | TextFeld::Style::VCenter );
	_o_ülps->setPosition( 2, 222 );
	_o_ülps->setSize( 100, 20 );
	_o_ülps->setRahmenFarbe( 0xFF00FF00 );
	_o_ülps->setSchriftZ( sNormal->getThis() );
	_o_ülps->setText( "" );
	_o_ülps->setSchriftFarbe( 0xFFFFFFFF );
	_o_ülps->setSchriftSize( 12 );
	_o_ülps->setAlphaFeldFarbe( 0x5500FF00 );
	_o_ülps->setAlphaFeldStrength( -5 );
	_o_ülps->setTastaturEreignis( _o_ülpsTE );
	_optionenF->addMember( _o_ülps );

	_o_üle = new AuswahlBox();
	_o_üle->setStyle( AuswahlBox::Style::Sichtbar | AuswahlBox::Style::Erlaubt | AuswahlBox::Style::Rahmen | AuswahlBox::Style::AuswahlBuffer |
					  AuswahlBox::Style::MausBuffer | AuswahlBox::Style::Hintergrund );
	_o_üle->setPosition( 104, 222 );
	_o_üle->setSize( 55, 20 );
	_o_üle->setSchriftZ( sNormal->getThis() );
	_o_üle->setRahmenFarbe( 0xFFFFFFFF );
	_o_üle->setHintergrundFarbe( 0xFF000000 );
	_o_üle->setAuswAlphaFeldFarbe( 0x5500FF00 );
	_o_üle->setAuswAlphaFeldStrength( -5 );
	_o_üle->setMausAlphaFeldFarbe( 0x2200FF00 );
	_o_üle->setMausAlphaFeldStrength( -5 );
	_o_üle->setMausEreignis( _ret1ME );
	_o_üle->setTastaturEreignis( _ret1TE );
	_o_üle->addEintrag( "kb/s" );
	_o_üle->addEintrag( "mb/s" );
	_optionenF->addMember( _o_üle );

	Knopf *o_ok = new Knopf();
	o_ok->setStyle( Knopf::Style::Sichtbar | Knopf::Style::Erlaubt | Knopf::Style::Buffered | Knopf::Style::KlickBuffer | Knopf::Style::Rahmen );
	o_ok->setPosition( 178, 254 );
	o_ok->setSize( 100, 20 );
	o_ok->setText( "Fertig" );
	o_ok->setSchriftZ( sNormal->getThis() );
	o_ok->setMausEreignis( o_okME );
	_optionenF->addMember( o_ok );

	screen->unlock();

	DWORD threadId;
	HANDLE handle = CreateThread( NULL, 0, runThread, screen, 0, &threadId );

	_patcher = new Patcher( (FBalken*)_fortschritt->getThis(), (TextFeld*)_aktion->getThis(), (Knopf*)_play->getThis(), &_exitB, mainClient->createPatchServerClient() );
	_patcher->startPatch();

	StartNachrichtenSchleife();

	_exitB = 1;
	WaitForSingleObject( handle, INFINITE );

	news->release();

	_patcher->warteAufPatch( INFINITE );
	int returnVal = _patcher->getReturn();
	_patcher->release();

	optionen->release();
	_optionenF->release();
	oReihenfolge->release();
	for( int i = 0; i < _o_rt->getZeilenAnzahl(); i++ )
	{
		if( _o_rt->zZeichnung( 0, i ) )
			( (TextFeld*)_o_rt->zZeichnung( 0, i ) )->release();
		if( _o_rt->zZeichnung( 1, i ) )
			( (KontrollKnopf*)_o_rt->zZeichnung( 1, i ) )->release();
		_o_rt->setZeichnungZ( 0, i, 0 );
		_o_rt->setZeichnungZ( 1, i, 0 );
	}
	_o_rt->release();
	_o_rno->release();
	_o_rnu->release();
	oLimit->release();
	_o_ülps->release();
	_o_üle->release();
	o_ok->release();

	hintergrund->release();
	close->release();
	minimieren->release();
	_fortschritt->release();
	_aktion->release();
	_kbps->release();
	_play->release();
	sNormal->release();

	patcherRahmen->release();
	patcherHintergrund->release();
	playBild->release();
	playKlick->release();
	systemSchließen->release();
	systemMinimieren->release();
	systemOptionen->release();
	systemFortschrittL->release();
	systemFortschrittV->release();

	screen->release();
	_frame->setBildschirm( 0 );
	_frame->zerstören();
	_frame->release();
	Network::Exit();

	DateiPfadErstellen( new Text( "data/tmp/keinabsturz" ) );

	if( _abbruch )
		return 0;
	return returnVal;
}