#include <DateiSystem.h>
#include <Datei.h>
#include <InitDatei.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;
    spieler = new RCArray< Spieler >();
    teams = new RCArray< Team >();
    erstellt = 0;
    sOnline = new Array< bool >();
    sBereit = new Array< bool >();
    gewinnerTeam = 0;
    ref = 1;
}

// Destruktor
Statistik::~Statistik()
{
    if( db )
        db->release();
    spieler->release();
    teams->release();
    sOnline->release();
    sBereit->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;
    for( auto s = spieler->getIterator(); s; s++ )
        zk->sendeSpielerStatistik( s );
    for( auto t = teams->getIterator(); t; t++ )
        zk->sendeTeamStatistik( t );
    zk->sendeStatistikLadenFertig();
    for( int i = 0; i < spieler->getEintragAnzahl(); 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::spielEnde( int team )
{
    gewinnerTeam = team;
}

void Statistik::setTeams( RCArray< Team > *zTeams )
{
    for( int i = 0; i < zTeams->getEintragAnzahl(); i++ )
        teams->set( zTeams->get( i ), i );
}

void Statistik::setSpieler( RCArray< Spieler > *zSpieler )
{
    for( int i = 0; i < zSpieler->getEintragAnzahl(); 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 < spieler->getEintragAnzahl(); 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 < spieler->getEintragAnzahl(); 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 < spieler->getEintragAnzahl(); 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 < spieler->getEintragAnzahl(); i++ )
        sOnline->set( spieler->z( i )->zKlient() && spieler->z( i )->zKlient()->istOnline(), i );
    // Statistik erstellen
    erstellt = 1;
    // Statistik senden
    for( int i = 0; i < spieler->getEintragAnzahl(); 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 < spieler->getEintragAnzahl(); 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;
}