#include "Neuigkeiten.h"
#include "../../Global/Variablen.h"
#include "../../Global/Initialisierung.h"
#include <Punkt.h>

// Inhalt der NewsThread Klasse aus Neuigkeiten.h
// Konstruktor
NewsThread::NewsThread( char *name, KSGScriptObj *obj, Neuigkeiten *n )
{
	scriptName = new Text( name );
	this->obj = obj;
	news = n;
	start();
}

// Destruktor
NewsThread::~NewsThread()
{
	scriptName->release();
	obj->release();
	news->release();
}

// nicht constant
void NewsThread::thread()
{
	bool trenn = 0;
	if( !newsKlient->istVerbunden() )
	{
		trenn = 1;
		if( !newsKlient->verbinde() )
		{
			news->endLaden( "Fehler beim Verbinden mit dem News-Server." );
			run = 0;
			delete this;
			return;
		}
	}
	if( !newsKlient->ladeSeite( scriptName->getText() ) )
	{
		news->endLaden( "Fehler beim herrunterladen der Seite." );
		run = 0;
		delete this;
		return;
	}
	if( trenn )
		newsKlient->trenne();
	Text *pfad = new Text( "data/tmp/news/" );
	pfad->anhängen( scriptName->getText() );
	pfad->anhängen( "/seite.ksgs" );
	obj->setScriptDatei( pfad );
	if( !obj->neuLaden() )
	{
		news->endLaden( "Fehler beim laden der Seite." );
		run = 0;
		delete this;
		return;
	}
	news->endLaden( 0 );
	run = 0;
	delete this;
}


void KSGSRückruf( void *p, RCArray< KSGSVariable > *parameter, KSGSVariable **ret )
{
	if( !p )
		return;
	( (Neuigkeiten*)p )->rückruf( parameter, ret );
}

// Inhalt der Neuigkeiten Klasse aus Neuigkeiten.h
// Konstruktor
Neuigkeiten::Neuigkeiten( Schrift *zSchrift, Fenster *zNachLoginFenster, int x )
{
	bildschirmGröße = BildschirmGröße();
	pos = Punkt( x, 67 );
	gr = Punkt( 102, 32 );
	rahmen = new LRahmen();
	rahmen->setFarbe( 0xFFFFFFFF );
	rahmen->setGröße( 102, 32 );
	alpha = 0;
	animation = 0;
	wirdGeladen = 0;
	sichtbar = 0;
	tickVal = 0;
	prozent1 = 0;
	prozent2 = 0;
	begPos = Punkt( 0, 0 );
	begGröße = Punkt( 0, 0 );
	größe1 = Punkt( 102, 32 );
	pos1 = Punkt( x, 67 );
	größe2 = Punkt( 800, 500 );
	pos2 = bildschirmGröße / 2 - größe2 / 2;
	fehler = initTextFeld( 5, 5, 790, 490, zSchrift, TextFeld::Style::Text & ~TextFeld::Style::Sichtbar, "" );
	laden = (Animation2D*)ladeAnimation->dublizieren();
	laden->setSichtbar( 0 );
	laden->setPosition( 375, 225 );
	zNachLoginFenster->addMember( this );
	ref = 1;
	ksgsDLL = dllDateien->ladeDLL( "KSGScript.dll", "data/bin/KSGScript.dll" );
	if( !ksgsDLL )
	{
		fehler->setText( "Die DLL Datei 'data/bin/KSGScript.dll' konnte nicht geladen werden." );
		fehler->addStyle( TextFeld::Style::Sichtbar );
		script = 0;
	}
	else
	{
		KSGSGetZeichnung getKSGSZeichnung = (KSGSGetZeichnung)GetProcAddress( ksgsDLL, KSGS_START_FUNKTION );
		if( !getKSGSZeichnung )
		{
			fehler->setText( "Die Funktion '" KSGS_START_FUNKTION "' konnte in der DLL Datei 'data/bin/KSGScript.dll'\nnicht gefunden werden." );
			fehler->addStyle( TextFeld::Style::Sichtbar );
			script = 0;
		}
		else
		{
			script = getKSGSZeichnung();
			script->setGröße( 800, 500 );
			script->setBildschirmZ( hauptScreen->getThis() );
			script->setSchriftZ( zSchrift->getThis() );
			script->setRückrufParam( this );
			script->setRückrufFunktion( KSGSRückruf );
			wirdGeladen = 1;
			laden->setSichtbar( 1 );
			new NewsThread( "Client/Start", script->getThis(), getThis() );
		}
	}
}

// Destruktor
Neuigkeiten::~Neuigkeiten()
{
	rahmen->release();
	if( script )
	{
		script->zurücksetzen();
		script->release();
	}
	if( ksgsDLL )
		dllDateien->releaseDLL( "KSGScript.dll" );
	fehler->release();
	laden->release();
}

// nicht constant
void Neuigkeiten::setSichtbar( bool sicht )
{
	begPos = pos;
	begGröße = gr;
	animation |= ( sicht ? 0x1 : 0x2 );
	rend = 1;
}

void Neuigkeiten::endLaden( char *err )
{
	laden->setSichtbar( 0 );
	wirdGeladen = 0;
	if( err )
	{
		fehler->setText( err );
		fehler->addStyle( TextFeld::Style::Sichtbar );
	}
	else
	{
		fehler->setText( "" );
		fehler->löscheStyle( TextFeld::Style::Sichtbar );
	}
}

void Neuigkeiten::rückruf( RCArray< KSGSVariable > *parameter, KSGSVariable **ret )
{
	if( wirdGeladen )
		return;
	KSGSVariable *befehl = parameter->z( 0 );
	if( !befehl )
		return;
	Text *b = befehl->getText();
	if( !b || !b->getLänge() )
	{
		if( b )
			b->release();
		return;
	}
	wirdGeladen = 1;
	laden->setSichtbar( 1 );
	new NewsThread( b->getText(), script->getThis(), getThis() );
}

void Neuigkeiten::doMausEreignis( MausEreignis &me )
{
	if( wirdGeladen )
		return;
	me.mx -= pos.x;
	me.my -= pos.y;
	if( script && sichtbar )
		script->doMausEreignis( me );
	me.mx += pos.x;
	me.my += pos.y;
}

void Neuigkeiten::doTastaturEreignis( TastaturEreignis &te )
{
	if( wirdGeladen )
		return;
	if( script && sichtbar )
		script->doTastaturEreignis( te );
}

bool Neuigkeiten::tick( double z )
{
	rend |= laden->tick( z );
	rend |= fehler->tick( z );
	if( wirdGeladen )
	{
		bool ret = rend;
		rend = 0;
		return ret;
	}
	if( script && sichtbar )
		rend |= script->tick( z );
	tickVal += z * 150;
	int val = (int)tickVal;
	if( val < 1 )
	{
		bool ret = rend;
		rend = 0;
		return ret;
	}
	tickVal -= val;
	if( ( animation | 0x1 ) == animation ) // Einblenden
	{
		if( prozent1 != 100 )
		{
			prozent1 += val;
			if( prozent1 >= 100 )
				prozent1 = 100;
			pos = begPos + (Punkt)( ( ( Vec2< double > )( pos2 - begPos ) / 100.0 ) * prozent1 );
			gr = begGröße + (Punkt)( ( ( Vec2< double > )( größe2 - begGröße ) / 100.0 ) * prozent1 );
		}
		else if( alpha != 255 )
		{
			alpha += val * 2;
			if( alpha >= 255 || ( animation | 0x2 ) == animation )
			{
				alpha = 255;
				animation &= ~0x1;
				sichtbar = 1;
				prozent1 = 0;
			}
		}
		rend = 1;
	}
	if( ( animation | 0x2 ) == animation ) // ausblenden
	{
		if( alpha != 0 )
		{
			alpha -= val * 2;
			if( alpha < 0 )
				alpha = 0;
		}
		else
		{
			prozent2 += val;
			if( prozent2 > 100 )
				prozent2 = 100;
			pos = begPos + (Punkt)( ( ( Vec2< double > )( pos1 - begPos ) / 100.0 ) * prozent2 );
			gr = begGröße + (Punkt)( ( ( Vec2< double > )( größe1 - begGröße ) / 100.0 ) * prozent2 );
			if( prozent2 == 100 )
			{
				prozent2 = 0;
				animation &= ~0x2;
				sichtbar = 0;
			}
		}
		rend = 1;
	}
	bool ret = rend;
	rend = 0;
	return ret;
}

void Neuigkeiten::render( Bild &zRObj )
{
	if( pos == pos1 )
		return;
	if( !zRObj.setDrawOptions( pos.x, pos.y, gr.x, gr.y ) )
		return;
	rahmen->setGröße( gr );
	rahmen->render( zRObj );
	int rbr = rahmen->getRBreite();
	zRObj.setAlpha( (unsigned char)alpha );
	fehler->render( zRObj );
	if( script )
		script->render( zRObj );
	laden->render( zRObj );
	zRObj.releaseAlpha();
	zRObj.releaseDrawOptions();
}

// constant
bool Neuigkeiten::istAnimiert() const
{
	return animation != 0;
}

bool Neuigkeiten::istSichtbar() const
{
	return sichtbar || prozent1 != 0;
}

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

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