#include "../../Global/Initialisierung.h"
#include <MausEreignis.h>
#include "../../Global/Variablen.h"

// Inhalt der UpdateGUI klasse aus UpdateGUI.h
// Konstruktor
UpdateGUI::UpdateGUI( Schrift *zSchrift, int spielId, int dg )
	: Thread()
{
	p = 0;
	updateStatus = initTextFeld( 0, 0, 302, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::VCenter, "Neuste Version Herunterladen" );
	updateStarten = initKnopf( 302, 0, 100, 20, zSchrift, Knopf::Style::Sichtbar, "Herunterladen" );
	updateFortschritt = initFBalken( 0, 25, 402, 22, zSchrift, FBalken::Style::Sichtbar | FBalken::Style::Hintergrund | FBalken::Style::HBild |
									 FBalken::Style::FBild | FBalken::Style::Rahmen | FBalken::Style::Prozent | FBalken::Style::L_R );
	updateAbbrechen = 1;
	sichtbar = 0;
	alpha = 0;
	this->spielId = spielId;
	this->dg = dg;
	ref = 1;
}

// Destruktor
UpdateGUI::~UpdateGUI()
{
	if( läuft() )
	{
		updateAbbrechen = 1;
		warteAufThread( 5000 );
		if( läuft() )
			ende();
	}
	updateStatus->release();
	updateStarten->release();
	updateFortschritt->release();
	if( p )
		p->release();
}

// nicht constant
void UpdateGUI::setSichtbar( bool sichtbar )
{
	this->sichtbar = sichtbar;
}

void UpdateGUI::doMausEreignis( MausEreignis &me, Patcher *zP )
{
	bool vera = me.verarbeitet;
	updateStarten->doMausEreignis( me );
	if( !vera && me.verarbeitet && me.id == ME_RLinks )
	{
		if( updateAbbrechen )
		{
			updateAbbrechen = 0;
			if( !p )
				p = zP->getThis();
			updateStarten->setText( "Abbrechen" );
			start();
		}
		else
		{
			updateAbbrechen = 1;
			if( läuft() )
				warteAufThread( 5000 );
			if( läuft() )
				ende();
			updateStatus->setText( "Neuste Version Herunterladen" );
			updateStarten->setText( "Herunterladen" );
			updateFortschritt->reset();
		}
	}
}

bool UpdateGUI::tick( double zeit )
{
	bool ret = updateStatus->tick( zeit );
	ret |= updateStarten->tick( zeit );
	ret |= updateFortschritt->tick( zeit );
	if( !alpha )
		ret = 0;
	if( sichtbar && alpha != 255 )
	{
		alpha += (int)( zeit * 150 );
		if( alpha > 255 )
			alpha = 255;
		ret = 1;
	}
	if( !sichtbar && alpha )
	{
		alpha -= (int)( zeit * 150 );
		if( alpha < 0 )
			alpha = 0;
		ret = 1;
	}
	return ret;
}

void UpdateGUI::render( int xOff, int yOff, Bild &zRObj )
{
	if( !zRObj.setDrawOptions( xOff, yOff, 402, 50 ) )
		return;
	zRObj.setAlpha( (unsigned char)alpha );
	updateStatus->render( zRObj );
	updateStarten->render( zRObj );
	updateFortschritt->render( zRObj );
	zRObj.releaseAlpha();
	zRObj.releaseDrawOptions();
}

void UpdateGUI::thread()
{
	int dgId = dg;
	if( spielId )
		dgId = infoKlient->getDateiGruppeIdVonSpiel( spielId );
	Text err;
	if( !p->update( dgId, &updateAbbrechen, updateFortschritt->getThis(), updateStatus->getThis(), &err ) )
	{
		if( nachLogin && nachLogin->zNachrichtenListe() )
			nachLogin->zNachrichtenListe()->addNachricht( new Text( "Fehler" ), err.getThis(), new Text( "Ok" ) );
	}
	updateStatus->setText( "Neuste Version Herunterladen" );
	updateStarten->setText( "Herunterladen" );
	updateFortschritt->reset();
	updateAbbrechen = 1;
	run = 0;
	if( nachLogin && nachLogin->zSpielenFenster() && spielId )
		nachLogin->zSpielenFenster()->updateErlaubt();
	if( nachLogin && nachLogin->zMGFenster() && dg )
		nachLogin->zMGFenster()->setAktuell( 1 );
}

// constant
bool UpdateGUI::istGleich( int spielId, int dg )
{
	return this->spielId == spielId && this->dg == dg;
}

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

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


// inhalt der UpdateHandler Klasse aus UpdateGUI.h
// Konstruktor
UpdateHandler::UpdateHandler()
{
	patcher = new Patcher();
	updates = new RCArray< UpdateGUI >();
	InitializeCriticalSection( &cs );
	ref = 1;
}

// Destruktor
UpdateHandler::~UpdateHandler()
{
	updates->release();
	patcher->release();
	DeleteCriticalSection( &cs );
}

// privat
void UpdateHandler::lock()
{
	EnterCriticalSection( &cs );
}

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

// nicht constant
void UpdateHandler::erstellen( Schrift *zSchrift, int spiel, int dg )
{
	lock();
	updates->add( new UpdateGUI( zSchrift, spiel, dg ) );
	unlock();
}

void UpdateHandler::setSichtbar( int spiel, bool sichtbar, int dg )
{
	lock();
	int anz = updates->getEintragAnzahl();
	for( int i = 0; i < anz; i++ )
	{
		if( updates->z( i )->istGleich( spiel, dg ) )
		{
			updates->z( i )->setSichtbar( sichtbar );
			break;
		}
	}
	unlock();
}

void UpdateHandler::doMausEreignis( int spiel, MausEreignis &me, int dg )
{
	lock();
	int anz = updates->getEintragAnzahl();
	for( int i = 0; i < anz; i++ )
	{
		if( updates->z( i )->istGleich( spiel, dg ) )
		{
			updates->z( i )->doMausEreignis( me, patcher );
			break;
		}
	}
	unlock();
}

bool UpdateHandler::tick( int spiel, double zeit, int dg )
{
	lock();
	bool ret = 0;
	int anz = updates->getEintragAnzahl();
	for( int i = 0; i < anz; i++ )
	{
		if( updates->z( i )->istGleich( spiel, dg ) )
		{
			ret = updates->z( i )->tick( zeit );
			break;
		}
	}
	unlock();
	return ret;
}

void UpdateHandler::render( int spiel, int xOff, int yOff, Bild &zRObj, int dg )
{
	lock();
	int anz = updates->getEintragAnzahl();
	for( int i = 0; i < anz; i++ )
	{
		if( updates->z( i )->istGleich( spiel, dg ) )
		{
			updates->z( i )->render( xOff, yOff, zRObj );
			break;
		}
	}
	unlock();
}

void UpdateHandler::lösche( int spiel, int dg )
{
	lock();
	int anz = updates->getEintragAnzahl();
	for( int i = 0; i < anz; i++ )
	{
		if( updates->z( i )->istGleich( spiel, dg ) )
		{
			updates->lösche( i );
			break;
		}
	}
	unlock();
}

bool UpdateHandler::hat( int spiel, int dg )
{
	lock();
	bool ret = 0;
	int anz = updates->getEintragAnzahl();
	for( int i = 0; i < anz; i++ )
	{
		if( updates->z( i )->istGleich( spiel, dg ) )
		{
			ret = 1;
			break;
		}
	}
	unlock();
	return ret;
}

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

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