#include "SpielLaden.h"
#include "..\..\..\Global\Variablen.h"
#include "..\..\..\Global\Initialisierung.h"
#include "..\..\..\Leser\KartenLeser.h"
#include <DateiSystem.h>
#include <Rahmen.h>
#include <AlphaFeld.h>
#include <Punkt.h>

// Inhalt der SpielLadenListeSpieler Klasse aus SpielLaden.h
// Konstruktor
SpielLadenListeSpieler::SpielLadenListeSpieler( int accountId, Schrift *zSchrift )
{
	rahmen = new LRahmen();
	rahmen->setGröße( 862, 22 );
	rahmen->setRamenBreite( 1 );
	rahmen->setFarbe( 0xFFFFFFFF );
	this->accountId = accountId;
	Text *n = infoKlient->getSpielerName( accountId );
	name = initTextFeld( 1, 1, 149, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::Center, n->getText() );
	n->release();
	team = initTextFeld( 230, 1, 100, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::Center, "0" );
	ping = initTextFeld( 410, 1, 50, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::Center, "0" );
	fortschritt = new FBalken();
	fortschritt->setStyle( FBalken::Style::Hintergrund | FBalken::Style::HBild | FBalken::Style::L_R | FBalken::Style::FBild | FBalken::Style::Prozent | FBalken::Style::Sichtbar );
	fortschritt->setSchriftZ( zSchrift->getThis() );
	fortschritt->setSFarbe( 0xFFFFFFFF );
	fortschritt->setSGröße( 12 );
	fortschritt->setPosition( 461, 1 );
	fortschritt->setGröße( 400, 20 );
	fortschritt->reset();
	fortschritt->setAktionAnzahl( 100 );
	Bild *fbhb = bilder->get( "system.ltdb/fortschritt lehr.png" );
	if( !fbhb )
	{
		LTDBDatei *datei = new LTDBDatei();
		datei->setDatei( new Text( "data/bilder/system.ltdb" ) );
		datei->leseDaten( 0 );
		fbhb = datei->laden( 0, new Text( "fortschrittleh" ) );
		datei->release();
		bilder->add( "system.ltdb/fortschritt lehr.png", fbhb->getThis() );
	}
	Bild *fbfhb = bilder->get( "system.ltdb/fortschritt voll.png" );
	if( !fbfhb )
	{
		LTDBDatei *datei = new LTDBDatei();
		datei->setDatei( new Text( "data/bilder/system.ltdb" ) );
		datei->leseDaten( 0 );
		fbfhb = datei->laden( 0, new Text( "fortschrittvol" ) );
		datei->release();
		bilder->add( "system.ltdb/fortschritt voll.png", fbfhb->getThis() );
	}
	fortschritt->setHintergrundBildZ( fbhb );
	fortschritt->setFBgBildZ( fbfhb );
	spielerFarbe = 0;
	teamFarbe = 0;
	p = 0;
	teamName = new Text( "" );
	rend = 0;
	ref = 1;
}

// Destruktor
SpielLadenListeSpieler::~SpielLadenListeSpieler()
{
	rahmen->release();
	name->release();
	team->release();
	ping->release();
	fortschritt->release();
	teamName->release();
}

// nicht constant
void SpielLadenListeSpieler::setFortschritt( int prozent )
{
	fortschritt->aktionPlus( prozent - fortschritt->getAktion() );
	rend = 1;
}

void SpielLadenListeSpieler::setPing( int ping )
{
	p = ping;
	rend = 1;
}

void SpielLadenListeSpieler::setTeamName( Text *zName )
{
	teamName->setText( zName->getText() );
	rend = 1;
}

void SpielLadenListeSpieler::setSpielerFarbe( int farbe )
{
	spielerFarbe = farbe;
	rend = 1;
}

void SpielLadenListeSpieler::setTeamFarbe( int farbe )
{
	teamFarbe = farbe;
	rend = 1;
}

bool SpielLadenListeSpieler::tick( double tickVal )
{
	if( !team->zText()->istGleich( teamName->getText() ) )
	{
		team->setText( teamName->getText() );
		rend = 1;
	}
	if( TextZuInt( ping->zText()->getText(), 10 ) != p )
	{
		ping->setText( "" );
		ping->zText()->anhängen( p );
		rend = 1;
	}
	bool ret = rend;
	rend = 0;
	return ret;
}

void SpielLadenListeSpieler::render( int y, Bild &zRObj )
{
	if( !zRObj.setDrawOptions( 0, y, 862, 22 ) )
		return;
	rahmen->render( zRObj );
	name->render( zRObj );
	zRObj.alphaRegion( 170, 1, 40, 20, spielerFarbe );
	team->render( zRObj );
	zRObj.alphaRegion( 350, 1, 40, 20, teamFarbe );
	ping->render( zRObj );
	fortschritt->render( zRObj );
	zRObj.releaseDrawOptions();
}

// constant
int SpielLadenListeSpieler::getAccountId() const
{
	return accountId;
}

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

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

// Inhalt der SpielLadenListe Klasse aus SpielLaden.h
// Konstruktor
SpielLadenListe::SpielLadenListe( Schrift *zSchrift )
{
	bildschirmGröße = BildschirmGröße();
	spielerAnzahl = 0;
	höhe = 0;
	breite = 0;
	tickVal = 0;
	spielerName = initTextFeld( 1, 1, 149, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::Center, "Spieler Name" );
	spielerFarbe = initTextFeld( 150, 1, 90, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::Center, "Spieler Farbe" );
	teamName = initTextFeld( 230, 1, 100, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::Center, "Team Name" );
	teamFarbe = initTextFeld( 330, 1, 80, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::Center, "Team Farbe" );
	ping = initTextFeld( 410, 1, 50, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::Center, "Ping" );
	fortschritt = initTextFeld( 460, 1, 400, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::Center, "Fortschritt" );
	rahmen = new LRahmen();
	rahmen->setFarbe( 0xFFFFFFFF );
	rahmen->setRamenBreite( 1 );
	titel = new AlphaFeld();
	titel->setFarbe( 0x1000FF00 );
	titel->setStärke( -15 );
	spieler = new RCArray < SpielLadenListeSpieler >();
	sts = 0;
	schrift = zSchrift->getThis();
	alpha = 0;
	animation = 0;
	rend = 0;
	ref = 1;
}

// Destruktor
SpielLadenListe::~SpielLadenListe()
{
	spielerName->release();
	spielerFarbe->release();
	teamName->release();
	teamFarbe->release();
	ping->release();
	fortschritt->release();
	rahmen->release();
	titel->release();
	spieler->release();
	schrift->release();
	if( sts )
		sts->release();
}

// nicht constant
void SpielLadenListe::setSTS( SpielerTeamStruktur *sts )
{
	if( this->sts )
		this->sts->release();
	this->sts = sts;
	rend = 1;
}

void SpielLadenListe::setSichtbar( bool sichtbar )
{
	animation = sichtbar ? 1 : 3;
}

void SpielLadenListe::addSpieler( int accountId, int spielerNummer )
{
	SpielLadenListeSpieler *tmp = new SpielLadenListeSpieler( accountId, schrift );
	int team = 0;
	int max = 0;
	int min = 0;
	for( int i = 0; i < sts->teamAnzahl; i++ )
	{
		min = max;
		max += sts->teamGröße->get( i );
		if( spielerNummer >= min && spielerNummer < max )
		{
			team = i;
			break;
		}
	}
	tmp->setSpielerFarbe( sts->spielerFarbe->hat( spielerNummer ) ? sts->spielerFarbe->get( spielerNummer ) : 0 );
	tmp->setTeamFarbe( sts->teamFarbe->hat( team ) ? sts->teamFarbe->get( team ) : 0 );
	tmp->setTeamName( sts->teamName->z( team ) );
	spieler->set( tmp, spielerAnzahl );
	spielerAnzahl++;
	rend = 1;
}

void SpielLadenListe::setSpielerFortschritt( int accountId, int prozent )
{
	for( int i = 0; i < spielerAnzahl; i++ )
	{
		if( spieler->z( i )->getAccountId() == accountId )
		{
			spieler->z( i )->setFortschritt( prozent );
			break;
		}
	}
}

void SpielLadenListe::setSpielerPing( int accountId, int ping )
{
	for( int i = 0; i < spielerAnzahl; i++ )
	{
		if( spieler->z( i )->getAccountId() == accountId )
		{
			spieler->z( i )->setPing( ping );
			break;
		}
	}
}

bool SpielLadenListe::tick( double tickVal )
{
	for( int i = 0; i < spielerAnzahl; i++ )
		rend |= spieler->z( i )->tick( tickVal );
	this->tickVal += tickVal * 500;
	int val = ( int )this->tickVal;
	if( !val )
	{
		bool ret = rend;
		rend = 0;
		return ret;
	}
	this->tickVal -= val;
	if( breite && animation != 4 && höhe != spielerAnzahl * 22 + 23 )
	{
		höhe += val / 2;
		if( höhe > spielerAnzahl * 22 + 23 )
			höhe = spielerAnzahl * 22 + 23;
		rend = 1;
	}
	switch( animation )
	{
	case 1: // größe ++
		breite += val;
		if( breite >= 864 )
		{
			breite = 864;
			animation = 2;
		}
		rend = 1;
		break;
	case 2: // alpha ++
		if( alpha + val > 255 )
		{
			alpha = 255;
			animation = 0;
		}
		else
			alpha += val;
		rend = 1;
		break;
	case 3: // alpha --
		if( alpha - val < 0 )
		{
			alpha = 0;
			animation = 4;
		}
		else
			alpha -= val;
		rend = 1;
		break;
	case 4: // größe --
		breite -= val;
		if( breite <= 0 )
		{
			breite = 0;
			höhe = 0;
			animation = 0;
		}
		else if( breite < spielerAnzahl * 22 + 23 )
			höhe = breite;
		rend = 1;
		break;
	}
	bool ret = rend;
	rend = 0;
	return ret;
}

void SpielLadenListe::render( Bild &zRObj )
{
	if( !breite )
		return;
	int x = bildschirmGröße.x / 2 - breite / 2;
	int y = bildschirmGröße.y / 2 - höhe / 2;
	if( !zRObj.setDrawOptions( x, y, breite, höhe ) )
		return;
	rahmen->setGröße( breite, höhe );
	rahmen->render( zRObj );
	zRObj.setAlpha( alpha );
	titel->setPosition( 1, 1 );
	titel->setGröße( breite - 2, 20 );
	titel->render( zRObj );
	spielerName->render( zRObj );
	spielerFarbe->render( zRObj );
	spielerName->render( zRObj );
	teamFarbe->render( zRObj );
	ping->render( zRObj );
	fortschritt->render( zRObj );
	zRObj.releaseAlpha();
	zRObj.drawLinieH( 1, 21, breite - 2, 0xFFFFFFFF );
	if( höhe > 22 )
	{
		if( !zRObj.setDrawOptions( 1, 22, breite - 2, höhe - 2 ) )
		{
			zRObj.releaseDrawOptions();
			return;
		}
		zRObj.alphaRegion( 0, 0, breite - 2, höhe - 23, 0x50000000 );
		zRObj.setAlpha( alpha );
		for( int i = 0; i < spielerAnzahl; i++ )
			spieler->z( i )->render( i * 22, zRObj );
		zRObj.releaseAlpha();
		zRObj.releaseDrawOptions();
	}
	zRObj.releaseDrawOptions();
}

// constant
int SpielLadenListe::getHöhe() const
{
	return höhe;
}

int SpielLadenListe::getAlpha() const
{
	return (int)alpha;
}

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

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

// Inhalt der SpielLaden Klasse aus SpielLaden.h
// Konstruktor
SpielLaden::SpielLaden( Schrift *zSchrift )
	: Thread()
{
	karteId = 0;
	bildschirmGröße = BildschirmGröße();
	hintergrundBild = 0;
	ladenAlpha = 0;
	hintergrundAlpha = 0;
	ladenBild = 0;
	tickVal = 0;
	geladen = 0;
	liste = new SpielLadenListe( zSchrift );
	animation = 0;
	ende = 0;
	rend = 0;
	ref = 1;
}

// Destruktor
SpielLaden::~SpielLaden()
{
	warteAufThread( 1000 );
	if( geladen )
		hintergrundBild->release();
	liste->release();
}

// nicht constant
void SpielLaden::setSpielerTeamStruktur( SpielerTeamStruktur *sts )
{
	liste->setSTS( sts );
	rend = 1;
}

void SpielLaden::setKarte( int karteId )
{
	this->karteId = karteId;
	start();
	rend = 1;
}

void SpielLaden::setSichtbar( bool sichtbar )
{
	animation = sichtbar ? 1 : 4;
}

void SpielLaden::thread()
{
	KartenLeser *reader = new KartenLeser();
	reader->setKarteId( karteId );
	hintergrundBild = reader->getLadeBild();
	reader->release();
	if( hintergrundBild )
		geladen = 1;
	else
		run = 0;
}

void SpielLaden::addSpieler( int accountId, int spielerNummer )
{
	liste->addSpieler( accountId, spielerNummer );
}

void SpielLaden::setSpielerFortschritt( int accountId, int prozent )
{
	liste->setSpielerFortschritt( accountId, prozent );
}

void SpielLaden::setSpielerPing( int accountId, int ping )
{
	liste->setSpielerPing( accountId, ping );
}

bool SpielLaden::tick( double tickVal )
{
	if( ende )
		return 0;
	rend |= liste->tick( tickVal );
	if( ladenAlpha )
		rend = 1;
	ladenBild++;
	if( ladenBild >= ladeAnimation->zAnimationData()->getBildAnzahl() )
		ladenBild = 0;
	if( !animation && geladen && ladenAlpha && !ende )
		animation = 2;
	this->tickVal += tickVal * 150;
	int val = ( int )this->tickVal;
	if( !val )
	{
		bool ret = rend;
		rend = 0;
		return ret;
	}
	this->tickVal -= val;
	switch( animation )
	{ // ------- Beginne zu laden -------
	case 1: // Sichtbar machen der Ladeanimation
		if( ladenAlpha + val >= 255 )
		{
			ladenAlpha = 255;
			animation = 0;
			if( geladen )
				animation = 2;
		}
		else
			ladenAlpha += val;
		rend = 1;
		break;
	case 2: // Sichtbar machen des Hintergrund Bildes
		if( hintergrundAlpha + val > 255 )
		{
			hintergrundAlpha = 255;
			animation = 3;
		}
		else
			hintergrundAlpha += val;
		rend = 1;
		break;
	case 3: // Unsichtbar machen der Lade Animation
		if( ladenAlpha == 255 )
			liste->setSichtbar( 1 ); // während dessen die Liste sichtbar machen
		if( ladenAlpha - val < 0 )
		{
			ladenAlpha = 0;
			animation = 0;
		}
		else
			ladenAlpha -= val;
		rend = 1;
		break;
		// ------- Laden beenden -------
	case 4: // Ladeanimation sichtbar machen
		if( !ladenAlpha && liste->getAlpha() == 255 )
			liste->setSichtbar( 0 ); // während dessen die Liste unsichtbar machen
		if( ladenAlpha + val > 255 )
		{
			ladenAlpha = 255;
			animation = 5;
		}
		else
			ladenAlpha += val;
		rend = 1;
		break;
	case 5: // Hintergrund Bild mit Lade Animation unsichtbar machen
		if( hintergrundAlpha - val < 0 )
		{
			hintergrundAlpha = 0;
			ladenAlpha = 0;
			ende = 1;
			animation = 0;
			spielKlient->bereitZumSpiel();
		}
		else
		{
			hintergrundAlpha -= val;
			ladenAlpha -= val;
		}
		rend = 1;
		break;
	}
	bool ret = rend;
	rend = 0;
	return ret;
}

void SpielLaden::render( Bild &zRObj )
{
	zRObj.setAlpha( hintergrundAlpha );
	if( hintergrundBild )
	{
		zRObj.drawBild( bildschirmGröße.x / 2 - hintergrundBild->getBreite() / 2, bildschirmGröße.y / 2 - hintergrundBild->getHöhe() / 2,
						hintergrundBild->getBreite(), hintergrundBild->getHöhe(), *hintergrundBild );
	}
	zRObj.releaseAlpha();
	liste->render( zRObj );
	zRObj.setAlpha( ladenAlpha );
	Bild *zLadenBild = ladeAnimation->zAnimationData()->zBild( ladenBild );
	zRObj.drawBild( bildschirmGröße.x / 2 - 25, bildschirmGröße.y / 2 - 25, zLadenBild->getBreite(), zLadenBild->getHöhe(), *zLadenBild );
	zRObj.releaseAlpha();
}

// constant
int SpielLaden::getAlpha() const
{
	return hintergrundAlpha;
}

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

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