#include "StatistikTabelle.h"
#include "Initialisierung.h"

#define ABSTYLE     AuswahlBox::Style::Sichtbar | AuswahlBox::Style::Erlaubt | AuswahlBox::Style::Rahmen | AuswahlBox::Style::AuswahlBuffer | AuswahlBox::Style::MausBuffer | AuswahlBox::Style::MaxHeight | AuswahlBox::Style::Hintergrund | AuswahlBox::Style::VScroll
#define OTSTYLE     ObjTabelle::Style::Sichtbar | ObjTabelle::Style::Erlaubt | ObjTabelle::Style::Rahmen | ObjTabelle::Style::Raster | ObjTabelle::Style::scroll | ObjTabelle::Style::SpaltenBreiteMax | ObjTabelle::Style::SpaltenBreiteMin | ObjTabelle::Style::SpaltenBreiteChangeable | ObjTabelle::Style::SpaltenBeweglich

// Inhalt der StatistikTabelle Klasse aus StatistikTabelle.h
// Konstruktor
StatistikTabelle::StatistikTabelle( Array< SSDSpieler * > *ssdgs, Array< SSDTeam * > *ssdgt,
                                    Schrift *zSchrift, Bildschirm *zScreen, bool historie )
    : schrift( zSchrift->getThis() ),
    ssdgs( ssdgs ),
    ssdgt( ssdgt ),
    stAuswahl( initAuswahlBox( 10, 10, 120, 20, zSchrift, ABSTYLE, { "Spieler", "Teams" } ) ),
    sortAuswahlGS( initAuswahlBox( 270, 10, 120, 20, zSchrift, ABSTYLE, { "Spielername", "Teamname",
    "Spielerfarbe", "Teamfarbe", "Schaden bekommen", "Schaden gemacht", "Leben geheilt",
    "Pr�zision", "Punkte", "Kills", "Tode", "Items aufgehoben", "Items benutzt" } ) ),
    sortAuswahlGT( initAuswahlBox( 270, 10, 120, 20, zSchrift, ABSTYLE, { "Teamname", "Teamfarbe",
    "Punkte", "Kills", "Tode" } ) ),
    sortRichtungGS( initAuswahlBox( 400, 10, 120, 20, zSchrift, ABSTYLE, { "Aufw�rts", "Abw�rts" } ) ),
    sortRichtungGT( initAuswahlBox( 400, 10, 120, 20, zSchrift, ABSTYLE, { "Aufw�rts", "Abw�rts" } ) ),
    gesamtSpieler( initObjTabelle( 10, 40, 760, 245, zSchrift, OTSTYLE, { { "Spielername", 120, 20, 200 },
    { "Teamname", 120, 20, 120 }, { "Spielerfarbe", 100, 20, 100 }, { "Teamfarbe", 100, 20, 100 },
    { "Schaden bekommen", 130, 20, 130 }, { "Schaden gemacht", 130, 20, 130 },
    { "Leben geheilt", 120, 20, 140 }, { "Pr�zision", 60, 20, 60 }, { "Punkte", 50, 20, 50 },
    { "Kills", 40, 20, 40 }, { "Tode", 40, 20, 40 }, { "Items aufgehoben", 120, 20, 120 },
    { "Items benutzt", 80, 20, 60 } }, 20 ) ),
    gesamtTeam( initObjTabelle( 10, 40, 760, 245, zSchrift, OTSTYLE, { { "Teamname", 120, 20, 120 },
    { "Teamfarbe", 100, 20, 100 }, { "Punkte", 50, 20, 50 }, { "Kills", 40, 20, 40 }, { "Tode", 40, 20, 40 } }, 20 ) ),
    teamS( 0 ),
    rend( 0 ),
    ref( 1 )
{
    tabelleF�llen( gesamtSpieler );
    tabelleF�llen( gesamtTeam );
    if( historie )
    {
        sortRichtungGS->setSize( 110, 20 );
        sortRichtungGT->setSize( 110, 20 );
        gesamtSpieler->setSize( 760, 380 );
        gesamtTeam->setSize( 760, 380 );
    }
}

// Destruktor
StatistikTabelle::~StatistikTabelle()
{
    schrift->release();
    ssdgs->release();
    ssdgt->release();
    stAuswahl->release();
    sortAuswahlGS->release();
    sortAuswahlGT->release();
    sortRichtungGS->release();
    sortRichtungGT->release();
    gesamtSpieler->release();
    gesamtTeam->release();
}

// privat
void StatistikTabelle::tabelleLehren( ObjTabelle *zT, bool �berschrift )
{
    int zAnz = zT->getZeilenAnzahl();
    for( int i = !�berschrift; i < zAnz; i++ )
        zT->removeZeile( !�berschrift );
}

void StatistikTabelle::tabelleF�llen( ObjTabelle *zT )
{
    if( zT == gesamtSpieler )
    {
        if( !sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() ) )
            return;
        if( !sortRichtungGS->zEintragText( sortRichtungGS->getAuswahl() ) )
            return;
        Array< int > reihenfolge;
        bool aufsteigend = sortRichtungGS->zEintragText( sortRichtungGS->getAuswahl() )->istGleich( "Aufw�rts" );
        int anz = ssdgs->getEintragAnzahl();
        bool *fertig = new bool[ anz ];
        ZeroMemory( fertig, anz );
        bool spielername = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Spielername" );
        bool teamname = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Teamname" );
        bool spielerfarbe = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Spielerfarbe" );
        bool teamfarbe = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Teamfarbe" );
        bool schadenBekommen = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Schaden bekommen" );
        bool schadenGemacht = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Schaden gemacht" );
        bool lebenGeheilt = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Leben geheilt" );
        bool pr�zision = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Pr�zision" );
        bool punkte = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Punkte" );
        bool kills = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Kills" );
        bool tode = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Tode" );
        bool itemsAufgehoben = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Items aufgehoben" );
        bool itemsBenutzt = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Items benutzt" );
        for( int i = 0; i < anz; i++ )
        {
            Text minMaxT;
            int minMax;
            int pos = -1;
            for( int j = 0; j < anz; j++ )
            {
                if( !ssdgs->hat( j ) || fertig[ j ] )
                    continue;
                if( spielername && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->spielerName < minMaxT ) || ( !aufsteigend && ssdgs->get( j )->spielerName > minMaxT ) ) )
                { // Sortiert nach Spieler Name
                    minMaxT = ssdgs->get( j )->spielerName.getText();
                    pos = j;
                }
                if( teamname && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->teamName < minMaxT ) || ( !aufsteigend && ssdgs->get( j )->teamName > minMaxT ) ) )
                { // Sortiert nach Team Name
                    minMaxT = ssdgs->get( j )->teamName.getText();
                    pos = j;
                }
                if( spielerfarbe && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->spielerFarbe < minMax ) || ( !aufsteigend && ssdgs->get( j )->spielerFarbe > minMax ) ) )
                { // Sortiert nach Spieler Farbe
                    minMax = ssdgs->get( j )->spielerFarbe;
                    pos = j;
                }
                if( teamfarbe && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->teamFarbe < minMax ) || ( !aufsteigend && ssdgs->get( j )->teamFarbe > minMax ) ) )
                { // Sortiert nach Team Farbe
                    minMax = ssdgs->get( j )->teamFarbe;
                    pos = j;
                }
                if( schadenBekommen && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->schadenBekommen < minMax ) || ( !aufsteigend && ssdgs->get( j )->schadenBekommen > minMax ) ) )
                { // Sortiert nach Schaden bekommen
                    minMax = ssdgs->get( j )->schadenBekommen;
                    pos = j;
                }
                if( schadenGemacht && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->schadenGemacht < minMax ) || ( !aufsteigend && ssdgs->get( j )->schadenGemacht > minMax ) ) )
                { // Sortiert nach Schaden gemacht
                    minMax = ssdgs->get( j )->schadenGemacht;
                    pos = j;
                }
                if( lebenGeheilt && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->lebenGeheilt < minMax ) || ( !aufsteigend && ssdgs->get( j )->lebenGeheilt > minMax ) ) )
                { // Sortiert nach Leben geheilt
                    minMax = ssdgs->get( j )->lebenGeheilt;
                    pos = j;
                }
                if( pr�zision && ( pos < 0 || ( aufsteigend && ( ssdgs->get( j )->treffer ? (int)( 100 / ( (double)ssdgs->get( j )->sch�sse / ssdgs->get( j )->treffer ) ) : 0 ) < minMax ) || ( !aufsteigend && ( 100 / ( ssdgs->get( j )->sch�sse / ssdgs->get( j )->treffer ) ) > minMax ) ) )
                { // Sortiert nach Treibstoff verbraucht
                    minMax = (int)( 100 / ( (double)ssdgs->get( j )->sch�sse / ssdgs->get( j )->treffer ) );
                    pos = j;
                }
                if( punkte && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->punkte < minMax ) || ( !aufsteigend && ssdgs->get( j )->punkte > minMax ) ) )
                { // Sortiert nach Punkten
                    minMax = ssdgs->get( j )->punkte;
                    pos = j;
                }
                if( kills && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->kills < minMax ) || ( !aufsteigend && ssdgs->get( j )->kills > minMax ) ) )
                { // Sortiert nach Kills
                    minMax = ssdgs->get( j )->kills;
                    pos = j;
                }
                if( tode && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->tode < minMax ) || ( !aufsteigend && ssdgs->get( j )->tode > minMax ) ) )
                { // Sortiert nach Toden
                    minMax = ssdgs->get( j )->tode;
                    pos = j;
                }
                if( itemsAufgehoben && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->itemsAufgehoben < minMax ) || ( !aufsteigend && ssdgs->get( j )->itemsAufgehoben > minMax ) ) )
                { // Sortiert nach Items aufgehoben
                    minMax = ssdgs->get( j )->itemsAufgehoben;
                    pos = j;
                }
                if( itemsBenutzt && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->itemsVerwendet < minMax ) || ( !aufsteigend && ssdgs->get( j )->itemsVerwendet > minMax ) ) )
                { // Sortiert nach Items benutzt
                    minMax = ssdgs->get( j )->itemsVerwendet;
                    pos = j;
                }
            }
            if( pos >= 0 )
            {
                reihenfolge.add( pos );
                fertig[ pos ] = 1;
            }
            else
                break;
        }
        delete[] fertig;
        anz = reihenfolge.getEintragAnzahl();
        for( int j = 0; j < anz; j++ )
        {
            int i = reihenfolge.get( j );
            zT->addZeile( Text( "Spieler " ) += ssdgs->get( i )->spielerNummer );
            int zNum = zT->getZeilenNummer( Text( "Spieler " ) += ssdgs->get( i )->spielerNummer );
            zT->setZeichnungZ( zT->getSpaltenNummer( "Spielername" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, ssdgs->get( i )->spielerName ) );
            zT->setZeichnungZ( zT->getSpaltenNummer( "Teamname" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, ssdgs->get( i )->teamName ) );
            zT->setZeichnungZ( zT->getSpaltenNummer( "Spielerfarbe" ), zNum, initTextFeld( 0, 0, 0, 0, 0, TextFeld::Style::Sichtbar | TextFeld::Style::Hintergrund, 0 ) );
            ( (TextFeld *)zT->zZeichnung( zT->getSpaltenNummer( "Spielerfarbe" ), zNum ) )->setHintergrundFarbe( ssdgs->get( i )->spielerFarbe );
            zT->setZeichnungZ( zT->getSpaltenNummer( "Teamfarbe" ), zNum, initTextFeld( 0, 0, 0, 0, 0, TextFeld::Style::Sichtbar | TextFeld::Style::Hintergrund, 0 ) );
            ( (TextFeld *)zT->zZeichnung( zT->getSpaltenNummer( "Teamfarbe" ), zNum ) )->setHintergrundFarbe( ssdgs->get( i )->teamFarbe );
            zT->setZeichnungZ( zT->getSpaltenNummer( "Schaden bekommen" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgs->get( i )->schadenBekommen ) );
            zT->setZeichnungZ( zT->getSpaltenNummer( "Schaden gemacht" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgs->get( i )->schadenGemacht ) );
            zT->setZeichnungZ( zT->getSpaltenNummer( "Leben geheilt" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgs->get( i )->lebenGeheilt ) );
            zT->setZeichnungZ( zT->getSpaltenNummer( "Pr�zision" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ( ssdgs->get( i )->sch�sse ? ( 100 * ssdgs->get( i )->treffer / ssdgs->get( i )->sch�sse ) : 0 ) ) );
            zT->setZeichnungZ( zT->getSpaltenNummer( "Punkte" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgs->get( i )->punkte ) );
            zT->setZeichnungZ( zT->getSpaltenNummer( "Kills" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgs->get( i )->kills ) );
            zT->setZeichnungZ( zT->getSpaltenNummer( "Tode" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgs->get( i )->tode ) );
            zT->setZeichnungZ( zT->getSpaltenNummer( "Items aufgehoben" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text( ssdgs->get( i )->itemsAufgehoben ) ) );
            zT->setZeichnungZ( zT->getSpaltenNummer( "Items benutzt" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text( ssdgs->get( i )->itemsVerwendet ) ) );
        }
        return;
    }
    if( zT == gesamtTeam )
    {
        if( !sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() ) )
            return;
        if( !sortRichtungGS->zEintragText( sortRichtungGS->getAuswahl() ) )
            return;
        Array< int > reihenfolge;
        bool aufsteigend = sortRichtungGT->zEintragText( sortRichtungGT->getAuswahl() )->istGleich( "Aufw�rts" );
        int anz = ssdgt->getEintragAnzahl();
        bool *fertig = new bool[ anz ];
        ZeroMemory( fertig, anz );
        bool teamname = sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() )->istGleich( "Teamname" );
        bool teamfarbe = sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() )->istGleich( "Teamfarbe" );
        bool punkte = sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() )->istGleich( "Punkte" );
        bool kills = sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() )->istGleich( "Kills" );
        bool tode = sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() )->istGleich( "Tode" );
        for( int i = 0; i < anz; i++ )
        {
            Text minMaxT;
            int minMax;
            int pos = -1;
            for( int j = 0; j < anz; j++ )
            {
                if( !ssdgt->hat( j ) || fertig[ j ] )
                    continue;
                if( teamname && ( pos < 0 || ( aufsteigend && ssdgt->get( j )->teamName < minMaxT ) || ( !aufsteigend && ssdgt->get( j )->teamName > minMaxT ) ) )
                { // Sortiert nach Team Name
                    minMaxT = ssdgt->get( j )->teamName.getText();
                    pos = j;
                }
                if( teamfarbe && ( pos < 0 || ( aufsteigend && ssdgt->get( j )->teamFarbe < minMax ) || ( !aufsteigend && ssdgt->get( j )->teamFarbe > minMax ) ) )
                { // Sortiert nach Team Farbe
                    minMax = ssdgt->get( j )->teamFarbe;
                    pos = j;
                }
                if( punkte && ( pos < 0 || ( aufsteigend && ssdgt->get( j )->punkte < minMax ) || ( !aufsteigend && ssdgt->get( j )->punkte > minMax ) ) )
                { // Sortiert nach Punkten
                    minMax = ssdgt->get( j )->punkte;
                    pos = j;
                }
                if( kills && ( pos < 0 || ( aufsteigend && ssdgt->get( j )->kills < minMax ) || ( !aufsteigend && ssdgt->get( j )->kills > minMax ) ) )
                { // Sortiert nach Kills
                    minMax = ssdgt->get( j )->kills;
                    pos = j;
                }
                if( tode && ( pos < 0 || ( aufsteigend && ssdgt->get( j )->tode < minMax ) || ( !aufsteigend && ssdgt->get( j )->tode > minMax ) ) )
                { // Sortiert nach Toden
                    minMax = ssdgt->get( j )->tode;
                    pos = j;
                }
            }
            if( pos >= 0 )
            {
                reihenfolge.add( pos );
                fertig[ pos ] = 1;
            }
            else
                break;
        }
        delete[] fertig;
        anz = reihenfolge.getEintragAnzahl();
        for( int j = 0; j < anz; j++ )
        {
            int i = reihenfolge.get( j );
            zT->addZeile( Text( "Team " ) += ssdgt->get( i )->teamNummer );
            int zNum = zT->getZeilenNummer( Text( "Team " ) += ssdgt->get( i )->teamNummer );
            zT->setZeichnungZ( zT->getSpaltenNummer( "Teamname" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, ssdgt->get( i )->teamName ) );
            zT->setZeichnungZ( zT->getSpaltenNummer( "Teamfarbe" ), zNum, initTextFeld( 0, 0, 0, 0, 0, TextFeld::Style::Sichtbar | TextFeld::Style::Hintergrund, 0 ) );
            ( (TextFeld *)zT->zZeichnung( zT->getSpaltenNummer( "Teamfarbe" ), zNum ) )->setHintergrundFarbe( ssdgt->get( i )->teamFarbe );
            zT->setZeichnungZ( zT->getSpaltenNummer( "Punkte" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgt->get( i )->punkte ) );
            zT->setZeichnungZ( zT->getSpaltenNummer( "Kills" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgt->get( i )->kills ) );
            zT->setZeichnungZ( zT->getSpaltenNummer( "Tode" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgt->get( i )->tode ) );
        }
        return;
    }
}

// nicht constant
void StatistikTabelle::doPublicMausEreignis( MausEreignis &me )
{
    // Auswahl Boxen
    int ausw = stAuswahl->getAuswahl();
    stAuswahl->doPublicMausEreignis( me );
    if( ausw != stAuswahl->getAuswahl() )
    {
        teamS = stAuswahl->zEintragText( stAuswahl->getAuswahl() )->istGleich( "Teams" );
        stAuswahl->einklappen();
    }
    if( teamS )
    { // Team Statistik
        int ausw = sortAuswahlGT->getAuswahl();
        sortAuswahlGT->doPublicMausEreignis( me );
        if( ausw != sortAuswahlGT->getAuswahl() )
        { // Sortierungs Spalte �ndert sich
            tabelleLehren( gesamtTeam, 0 );
            tabelleF�llen( gesamtTeam );
            sortAuswahlGT->einklappen();
        }
        ausw = sortRichtungGT->getAuswahl();
        sortRichtungGT->doPublicMausEreignis( me );
        if( ausw != sortRichtungGT->getAuswahl() )
        { // Sortierungs Richtung �ndert sich
            tabelleLehren( gesamtTeam, 0 );
            tabelleF�llen( gesamtTeam );
            sortRichtungGT->einklappen();
        }
        gesamtTeam->doPublicMausEreignis( me );
    }
    else
    { // Spieler Statistik
        int ausw = sortAuswahlGS->getAuswahl();
        sortAuswahlGS->doPublicMausEreignis( me );
        if( ausw != sortAuswahlGS->getAuswahl() )
        { // Sortierungs Spalte �ndert sich
            tabelleLehren( gesamtSpieler, 0 );
            tabelleF�llen( gesamtSpieler );
            sortAuswahlGS->einklappen();
        }
        ausw = sortRichtungGS->getAuswahl();
        sortRichtungGS->doPublicMausEreignis( me );
        if( ausw != sortRichtungGS->getAuswahl() )
        { // Sortierungs Richtung �ndert sich
            tabelleLehren( gesamtSpieler, 0 );
            tabelleF�llen( gesamtSpieler );
            sortRichtungGS->einklappen();
        }
        gesamtSpieler->doPublicMausEreignis( me );
    }
}

bool StatistikTabelle::tick( double tickVal )
{
    if( teamS )
    { // Team Statistik
        rend |= gesamtTeam->tick( tickVal );
        rend |= sortAuswahlGT->tick( tickVal );
        rend |= sortRichtungGT->tick( tickVal );
    }
    else
    { // Spieler Statistik
        rend |= gesamtSpieler->tick( tickVal );
        rend |= sortAuswahlGS->tick( tickVal );
        rend |= sortRichtungGS->tick( tickVal );
    }
    // Auswahl Boxen
    rend |= stAuswahl->tick( tickVal );
    bool ret = rend;
    rend = 0;
    return ret;
}

void StatistikTabelle::render( Bild &zRObj )
{
    if( teamS )
    { // Team Statistik
        gesamtTeam->render( zRObj );
        sortAuswahlGT->render( zRObj );
        sortRichtungGT->render( zRObj );
    }
    else
    { // Spieler Statistik
        gesamtSpieler->render( zRObj );
        sortAuswahlGS->render( zRObj );
        sortRichtungGS->render( zRObj );
    }
    // Auswahl Boxen
    stAuswahl->render( zRObj );
}

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

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