#include <DateiSystem.h>
#include <Datei.h>
#include "Spieler.h"
#include "Team.h"
#include "SSKlient.h"
#ifndef WIN32
#define Sleep( x )    usleep( (x) * 1000 )
#endif
#include "Statistik.h"

// Inhalt der Statistik Klasse aus Statistik.h
// Konstruktor
Statistik::Statistik()
{
	spielId = 0;
	karteId = 0;
	db = 0;
	spielerAnzahl = 0;
	spieler = new RCArray< Spieler >();
	erstellt = 0;
	sOnline = new Array< bool >();
	sBereit = new Array< bool >();
	gss = new RCArray< SpielerStatistik >();
	gts = new RCArray< TeamStatistik >();
	teamNamen = 0;
	gewinnerTeam = 0;
	ref = 1;
}

// Destruktor
Statistik::~Statistik()
{
	if( db )
		db->release();
	spieler->release();
	sOnline->release();
	sBereit->release();
	gss->release();
	gts->release();
	if( teamNamen )
		teamNamen->release();
}

// privat
void Statistik::sendeStatistik( int index )
{ // Sendet Statistik an Spieler index
	if( !sOnline->hat( index ) || !sOnline->get( index ) )
		return;
	Klient *zk = spieler->z( index )->zKlient();
	if( !zk )
		return;
	int anz = gss->getEintragAnzahl();
	for( int i = 0; i < anz; i++ )
		zk->sendeSpielerStatistik( gss->z( i ) );
	anz = gts->getEintragAnzahl();
	for( int i = 0; i < anz; i++ )
		zk->sendeTeamStatistik( gts->z( i ) );
	zk->sendeStatistikLadenFertig();
	for( int i = 0; i < spielerAnzahl; i++ )
	{
		if( !sOnline->hat( i ) || !sOnline->get( i ) )
			zk->sendeStatistikSpielerOffline( spieler->z( i )->getAccountId() );
	}
}

// nicht constant
void Statistik::setSpielId( int id )
{
	spielId = id;
}

void Statistik::setKarteId( int id )
{
	karteId = id;
}

void Statistik::setPSQLDB( SSDatenbankV *db )
{
	if( this->db )
		this->db->release();
	this->db = db;
}

void Statistik::setTeamNamen( RCArray< Text > *namen )
{
	if( teamNamen )
		teamNamen->release();
	teamNamen = namen;
}

void Statistik::spielEnde( int team )
{
	gewinnerTeam = team;
}

void Statistik::setSpieler( int anzahl, RCArray< Spieler > *zSpieler )
{
	spielerAnzahl = anzahl;
	for( int i = 0; i < anzahl; i++ )
	{
		spieler->set( zSpieler->get( i ), i );
		sOnline->set( 0, i );
		sBereit->set( 0, i );
	}
}

void Statistik::klientOffline( int accountId )
{
	for( int i = 0; i < spielerAnzahl; i++ )
	{
		if( spieler->z( i )->getAccountId() == accountId )
		{
			sOnline->set( 0, i );
			sBereit->set( 0, i );
		}
		else if( sOnline->hat( i ) && sOnline->get( i ) && spieler->z( i )->zKlient() )
			spieler->z( i )->zKlient()->sendeStatistikSpielerOffline( accountId );
	}
}

void Statistik::statistikAnfrage( int accountId, short len, char *bytes )
{
	len--;
	switch( *bytes )
	{
	case 0: // Spieler ist Bereit
		for( int i = 0; i < spielerAnzahl; i++ )
		{
			if( !erstellt )
			{
				if( spieler->z( i )->getAccountId() == accountId )
					sBereit->set( 1, i );
			}
			else if( spieler->z( i )->getAccountId() == accountId )
			{
				sendeStatistik( i );
				break;
			}
		}
		break;
	case 1: // Chat Nachricht
		bytes++;
		char *txt = new char[ len + 1 ];
		txt[ len ] = 0;
		for( int i = 0; i < len; i++ )
			txt[ i ] = bytes[ i ];
		for( int i = 0; i < spielerAnzahl; i++ )
		{
			if( sOnline->hat( i ) && sOnline->get( i ) && spieler->z( i )->zKlient() )
				spieler->z( i )->zKlient()->sendeStatistikChatNachricht( accountId, txt );
		}
		delete[] txt;
		break;
	}
}

void Statistik::run()
{
	for( int i = 0; i < spielerAnzahl; i++ )
		sOnline->set( spieler->z( i )->istOnline(), i );
	// Statistik erstellen
	// gesammt Spieler
	for( int i = 0; i < spielerAnzahl; i++ )
	{
		if( spieler->z( i ) )
		{
			Spieler *tmp = spieler->z( i );
			InitDatei *d = new InitDatei();
			Text w;
			w = tmp->getSpielerNummer();
			if( w.getLength() )
				d->addWert( "SpielerNummer", w.getText() );
			Text *sn = db->getAccountRufName( tmp->getAccountId() );
			if( sn && sn->getLength() )
				d->addWert( "SpielerName", sn->getText() );
			if( sn )
				sn->release();
			d->addWert( "TeamName", tmp->zTeam()->name );
			w = tmp->getSpielerFarbe();
			if( w.getLength() )
				d->addWert( "SpielerFarbe", w.getText() );
			w = tmp->zTeam()->farbe;
			if( w.getLength() )
				d->addWert( "TeamFarbe", w.getText() );
			w = tmp->getSchadenBekommen();
			if( w.getLength() )
				d->addWert( "SchadenBekommen", w.getText() );
			w = tmp->getSchadenGemacht();
			if( w.getLength() )
				d->addWert( "SchadenGemacht", w.getText() );
			w = tmp->getTreibstoffVerbraucht();
			if( w.getLength() )
				d->addWert( "TreibstoffVerbraucht", w.getText() );
			w = tmp->getShots();
			if( w.getLength() )
				d->addWert( "Schüsse", w.getText() );
			w = tmp->getTreffer();
			if( w.getLength() )
				d->addWert( "Treffer", w.getText() );
			w = tmp->getPunkte();
			if( w.getLength() )
				d->addWert( "Punkte", w.getText() );
			w = tmp->getKills();
			if( w.getLength() )
				d->addWert( "Kills", w.getText() );
			w = tmp->getTode();
			if( w.getLength() )
				d->addWert( "Tode", w.getText() );
			w = tmp->getZeitAmLeben();
			if( w.getLength() )
				d->addWert( "ZeitAmLeben", w.getText() );
			w = tmp->getZeitTod();
			if( w.getLength() )
				d->addWert( "ZeitTod", w.getText() );
			SpielerStatistik *gss = new SpielerStatistik();
			gss->initValues( d );
			this->gss->add( gss );
		}
	}
	// Gesamt Team
	for( int i = 0; i < spielerAnzahl; i++ )
	{
		Spieler *tmp = spieler->z( i );
		if( tmp )
		{
			int anz = gts->getEintragAnzahl();
			bool gefunden = 0;
			for( int j = 0; j < anz; j++ )
			{
				if( gts->z( j ) && gts->z( j )->getTeamNummer() == tmp->zTeam()->id )
				{
					gefunden = 1;
					break;
				}
			}
			if( gefunden )
				continue;
			InitDatei *d = new InitDatei();
			Text w;
			w = tmp->zTeam()->id;
			if( w.getLength() )
				d->addWert( "TeamNummer", w.getText() );
			d->addWert( "TeamName", tmp->zTeam()->name );
			w = tmp->zTeam()->farbe;
			if( w.getLength() )
				d->addWert( "TeamFarbe", w.getText() );
			int schadenBekommen = 0;
			int schadenGemacht = 0;
			int treibstoffVerbraucht = 0;
			int shots = 0;
			int treffer = 0;
			int punkte = 0;
			int kills = 0;
			int tode = 0;
			for( int j = 0; j < spielerAnzahl; j++ )
			{
				Spieler *s = spieler->z( j );
				if( s && s->zTeam()->id == tmp->zTeam()->id )
				{
					schadenBekommen += s->getSchadenBekommen();
					schadenGemacht += s->getSchadenGemacht();
					treibstoffVerbraucht += s->getTreibstoffVerbraucht();
					shots += s->getShots();
					treffer += s->getTreffer();
					punkte += s->getPunkte();
					kills += s->getKills();
					tode += s->getTode();
				}
			}
			w = schadenBekommen;
			if( w.getLength() )
				d->addWert( "SchadenBekommen", w.getText() );
			w = schadenGemacht;
			if( w.getLength() )
				d->addWert( "SchadenGemacht", w.getText() );
			w = treibstoffVerbraucht;
			if( w.getLength() )
				d->addWert( "TreibstoffVerbraucht", w.getText() );
			w = shots;
			if( w.getLength() )
				d->addWert( "Schüsse", w.getText() );
			w = treffer;
			if( w.getLength() )
				d->addWert( "Treffer", w.getText() );
			w = punkte;
			if( w.getLength() )
				d->addWert( "Punkte", w.getText() );
			w = kills;
			if( w.getLength() )
				d->addWert( "Kills", w.getText() );
			w = tode;
			if( w.getLength() )
				d->addWert( "Tode", w.getText() );
			w = (int)( gewinnerTeam == tmp->zTeam()->id );
			if( w.getLength() )
				d->addWert( "Gewonnen", w.getText() );
			TeamStatistik *gts = new TeamStatistik();
			gts->initValues( d );
			this->gts->add( gts );
		}
	}
	erstellt = 1;
	// Statistik senden
	for( int i = 0; i < spielerAnzahl; i++ )
	{
		if( sBereit->hat( i ) && sBereit->get( i ) )
			sendeStatistik( i );
	}
	// Statistik speichern
	Text *pfad = new Text( "../spiel log/" );
	pfad->append( spielId );
	pfad->append( "/fertig" );
	DateiPfadErstellen( pfad );
	// warten bis alle verlassen haben
	while( 1 )
	{
		Sleep( 1000 );
		int online = 0;
		for( int i = 0; i < spielerAnzahl; i++ )
			online += sOnline->hat( i ) && sOnline->get( i );
		if( !online )
			break;
	}
}

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

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