#include "Men�.h"
#include "Initialisierung.h"
#include <MausEreignis.h>
#include <Textfeld.h>
#include <InitDatei.h>
#include <Text.h>
#include <Datei.h>
#include <TastaturEreignis.h>
#include <KSGTDatei.h>
#include <Schrift.h>
#include <DateiSystem.h>
#include <Rahmen.h>
#include <Bildschirm.h>
#include <AsynchronCall.h>

// Inhalt der Men�Verloren Klasse aus Men�.h
// Kontruktor
Men�Verloren::Men�Verloren( Schrift *zSchrift )
{
    ram = new LRahmen();
    ram->setSize( 160, 100 );
    ram->setPosition( 320, 200 );
    ram->setFarbe( 0xFFFFFFFF );
    verloren = initTextFeld( 325, 210, 150, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::Center, "Du hast verloren." );
    neu = initKnopf( 350, 240, 100, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::Center, "Neues Spiel" );
    beenden = initKnopf( 350, 270, 100, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::Center, "Zur�ck" );
    ref = 1;
}

// Destruktor
Men�Verloren::~Men�Verloren()
{
    verloren->release();
    neu->release();
    beenden->release();
    ram->release();
}

// nicht constant
int Men�Verloren::doMausEreignis( MausEreignis &me )
{
    bool vera = me.verarbeitet;
    int ret = 0;
    neu->doMausEreignis( me );
    if( !vera && me.verarbeitet && me.id == ME_RLinks )
        ret = 1;
    beenden->doMausEreignis( me );
    if( !vera && me.verarbeitet && !ret && me.id == ME_RLinks )
        ret = 2;
    return ret;
}

bool Men�Verloren::tick( double tickVal )
{
    bool ret = verloren->tick( tickVal );
    ret |= neu->tick( tickVal );
    ret |= beenden->tick( tickVal );
    return ret;
}

void Men�Verloren::render( Bild &zRObj )
{
    zRObj.alphaRegion( ram->getX(), ram->getY(), ram->getBreite(), ram->getHeight(), 0xD0000000 );
    verloren->render( zRObj );
    neu->render( zRObj );
    beenden->render( zRObj );
    ram->render( zRObj );
}

// Reference Counting
Men�Verloren *Men�Verloren::getThis()
{
    ref++;
    return this;
}

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


// Inhalt der Men�Spiel Klasse aus Men�.h
// Konstruktor
Men�Spiel::Men�Spiel( Schrift *zSchrift, Bildschirm *zScreen, KSGClient::MinigameServerClient *klient )
{
    scoreT = initTextFeld( 690, 10, 100, 20, zSchrift, TextFeld::Style::Text, "Score: 0" );
    beenden = initKnopf( 690, 40, 100, 20, zSchrift, Knopf::Style::Sichtbar, "Beenden" );
    map = new Map( klient );
    verloren = new Men�Verloren( zSchrift );
    timePuffer = 0;
    beendet = 0;
    ref = 1;
}

// Destruktor
Men�Spiel::~Men�Spiel()
{
    scoreT->release();
    beenden->release();
    map->release();
    verloren->release();
}

// nicht constant
void Men�Spiel::reset()
{
    timePuffer = 0;
    Text optionen = "Width=";
    InitDatei *opd = new InitDatei( "data/Minigames/Bl�cke/data/optionen.ini" );
    if( !opd->laden() )
        DateiPfadErstellen( "data/Minigames/Bl�cke/data/optionen.ini" );
    if( opd->wertExistiert( "Breite" ) )
        optionen += (int)*opd->zWert( "Breite" );
    else
    {
        opd->addWert( "Breite", "20" );
        optionen += 20;
    }
    optionen += ",Height=";
    if( opd->wertExistiert( "Height" ) )
        optionen += (int)*opd->zWert( "Height" );
    else
    {
        opd->addWert( "Height", "12" );
        optionen += 12;
    }
    optionen += ",Farben=";
    if( opd->wertExistiert( "Farben" ) )
        optionen += (int)*opd->zWert( "Farben" );
    else
    {
        opd->addWert( "Farben", "5" );
        optionen += 5;
    }
    optionen += ",Speed=";
    if( opd->wertExistiert( "Geschwindigkeit" ) )
        optionen += (int)*opd->zWert( "Geschwindigkeit" );
    else
    {
        opd->addWert( "Geschwindigkeit", "4000" );
        optionen += 4000;

    }
    optionen += ",Fortsetzen=";
    if( opd->wertExistiert( "Fortsetzen" ) )
        optionen += (int)*opd->zWert( "Fortsetzen" ) != 0;
    else
    {
        opd->addWert( "Fortsetzen", "0" );
        optionen += 0;

    }
    optionen += ",Seed=0";
    opd->speichern();
    opd->release();
    map->reset( &optionen );
    beendet = 0;
    scoreT->setText( "Score: " );
    scoreT->zText()->append( map->getScore() );
}

void Men�Spiel::doMausEreignis( MausEreignis &me )
{
    bool vera = me.verarbeitet;
    beenden->doMausEreignis( me );
    if( !vera && me.verarbeitet && me.id == ME_RLinks )
    {
        map->speichern();
        beendet = 1;
    }
    map->doMausEreignis( me );
    scoreT->setText( "Score: " );
    scoreT->zText()->append( map->getScore() );
    if( map->istBeendet() )
    {
        int ak = verloren->doMausEreignis( me );
        if( ak == 1 )
            reset();
        if( ak == 2 )
            beendet = 1;
    }
}

void Men�Spiel::doTastaturEreignis( TastaturEreignis &te )
{
    if( map->istBeendet() )
    {
        if( te.id == TE_Release && te.taste == T_Enter )
            reset();
        if( te.id == TE_Release && te.taste == T_BackSpace )
            beendet = 1;
        return;
    }
    map->doTastaturEreignis( te );
}

bool Men�Spiel::tick( double tickVal )
{
    bool ret = beenden->tick( tickVal );
    timePuffer += tickVal;
    while( timePuffer >= 0.01 )
    {
        ret |= map->tick( 0.01 );
        timePuffer -= 0.01;
    }
    ret |= map->tick( tickVal );
    if( map->istBeendet() )
        ret |= verloren->tick( tickVal );
    return ret;
}

void Men�Spiel::render( Bild &zRObj )
{
    map->render( zRObj );
    scoreT->render( zRObj );
    beenden->render( zRObj );
    if( map->istBeendet() )
        verloren->render( zRObj );
}

// constant
bool Men�Spiel::istBeendet() const
{
    return beendet;
}

// Reference Counting
Men�Spiel *Men�Spiel::getThis()
{
    ref++;
    return this;
}

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


// Inhalt der Men�Wiederhohlung Klasse
// Konstruktor
Men�Wiederhohlung::Men�Wiederhohlung( Schrift *zSchrift, Bildschirm *zScreen, Datei *datei, Text *zOptionen )
{
    scoreT = initTextFeld( 690, 10, 100, 20, zSchrift, TextFeld::Style::Text, "Score: 0" );
    beenden = initKnopf( 690, 40, 100, 20, zSchrift, Knopf::Style::Sichtbar, "Beenden" );
    this->datei = datei;
    if( !datei->istOffen() )
        datei->open( Datei::Style::lesen );
    __int64 seed;
    datei->lese( (char*)&seed, 8 );
    zOptionen->append( ",Fortsetzen=0,Seed=" );
    zOptionen->append( seed );
    map = new Map( 0 );
    map->reset( zOptionen );
    beendet = 0;
    nowTime = 0;
    nextTime = 0;
    datei->lese( (char*)&nextTime, 8 );
    timePuffer = 0;
    ref = 1;
}

// Destruktor
Men�Wiederhohlung::~Men�Wiederhohlung()
{
    scoreT->release();
    beenden->release();
    map->release();
    datei->close();
    datei->release();
}

// nicht constant
void Men�Wiederhohlung::doMausEreignis( MausEreignis &me )
{
    bool vera = me.verarbeitet;
    beenden->doMausEreignis( me );
    if( !vera && me.verarbeitet && me.id == ME_RLinks )
        beendet = 1;
    if( map->istBeendet() )
        beendet = 1;
}

void Men�Wiederhohlung::doTastaturEreignis( TastaturEreignis &te )
{}

bool Men�Wiederhohlung::tick( double tickVal )
{
    bool ret = beenden->tick( tickVal );
    // TODO Replay Activity
    while( nextTime >= 0 && nowTime + tickVal >= nextTime )
    {
        while( nowTime < nextTime )
        {
            ret |= map->tick( 0.01 );
            tickVal -= 0.01;
            nowTime += 0.01;
        }
        char ak;
        MausEreignis me;
        datei->lese( &ak, 1 );
        me.id = ME_RRechts;
        if( ak == 0 )
        {
            datei->lese( (char*)&me.mx, 4 );
            datei->lese( (char*)&me.my, 4 );
            me.id = ME_RLinks;
        }
        if( datei->istEnde() )
            nextTime = -1;
        else
            datei->lese( (char*)&nextTime, 8 );
        me.verarbeitet = 0;
        map->doMausEreignis( me );
    }
    timePuffer += tickVal;
    while( timePuffer > 0 )
    {
        ret |= map->tick( 0.01 );
        nowTime += 0.01;
        timePuffer -= 0.01;
    }
    scoreT->setText( "Score: " );
    scoreT->zText()->append( map->getScore() );
    return ret;
}

void Men�Wiederhohlung::render( Bild &zRObj )
{
    map->render( zRObj );
    scoreT->render( zRObj );
    beenden->render( zRObj );
}

// constant
bool Men�Wiederhohlung::istBeendet() const
{
    return beendet;
}

// Reference Counting
Men�Wiederhohlung *Men�Wiederhohlung::getThis()
{
    ref++;
    return this;
}

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

// Inhalt der Men�Statistik Klasse aus Men�.h
// Konstruktor
Men�Statistik::Men�Statistik( Schrift *zSchrift, Bildschirm *zScreen, KSGClient::MinigameServerClient *klient )
{
    this->klient = klient;
    wiederH = 0;
    ansichtT = initTextFeld( 245, 10, 50, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::VCenter, "Ansicht:" );
    ansicht = initAuswahlBox( 295, 10, 120, 20, zSchrift, AuswahlBox::Style::Normal | AuswahlBox::Style::Hintergrund, { "Tabelle", "Diagramm" } );
    optionen = initKontrollKnopf( 425, 10, 130, 20, zSchrift, KontrollKnopf::Style::Normal, "Optionen beachten" );
    worldBestT = initObjTabelle( 150, 40, 500, 120, zSchrift, ObjTabelle::Style::normal | ObjTabelle::Style::VScroll, { { "Score", 60, 0, 0 }, { "Spieler", 100, 0, 0 }, { "Ansehen", 55, 0, 0 }, { "Breite", 70, 0, 0 },{ "Height", 70, 0, 0 },{ "Farben", 65, 0, 0 },{ "Tempo", 60, 0, 0 } }, 20 );
    gesammtT = initObjTabelle( 150, 170, 500, 290, zSchrift, ObjTabelle::Style::normal | ObjTabelle::Style::VScroll, { { "Score", 70, 0, 0 }, { "Datum", 145, 0, 0 }, { "Breite", 70, 0, 0 }, { "Height", 70, 0, 0 }, { "Farben", 65, 0, 0 }, { "Tempo", 60, 0, 0 } }, 20 );
    optionenT = initObjTabelle( 150, 170, 500, 290, zSchrift, ObjTabelle::Style::normal | ObjTabelle::Style::VScroll, { { "Score", 70, 0, 0 }, { "Datum", 145, 0, 0 }, { "Breite", 70, 0, 0 }, { "Height", 70, 0, 0 }, { "Farben", 65, 0, 0 }, { "Tempo", 60, 0, 0 } }, 20 );
    gesammtD = initLinienDiagramm( 100, 170, 600, 290, zSchrift, LDiag::Style::DatenRahmen, 0 );
    optionenD = initLinienDiagramm( 100, 170, 600, 290, zSchrift, LDiag::Style::DatenRahmen, 0 );
    removen = initKnopf( 10, 470, 100, 20, zSchrift, Knopf::Style::Sichtbar, "Zur�cksetzen" );
    zur�ck = initKnopf( 350, 470, 100, 20, zSchrift, Knopf::Style::Sichtbar, "Zur�ck" );
    schrift = zSchrift->getThis();
    tr = new TextRenderer( schrift->getThis() );
    screen = zScreen->getThis();
    asyncFinished = 1;
}

// Destruktor
Men�Statistik::~Men�Statistik()
{
    while( !asyncFinished )
    {
        Sleep( 100 );
    }
    tr->release();
    worldBestT->release();
    ansichtT->release();
    ansicht->release();
    optionen->release();
    gesammtT->release();
    optionenT->release();
    gesammtD->release();
    optionenD->release();
    removen->release();
    zur�ck->release();
    schrift->release();
    klient->release();
    if( wiederH )
        wiederH->release();
    screen->release();
}

// nicht constant
void Men�Statistik::reset()
{
    ObjTabelle *tmpWBT = (ObjTabelle*)worldBestT->getThis();
    KSGClient::MinigameServerClient *tmpKlient = klient->getThis();
    Schrift *tmpSchrift = schrift->getThis();
    asyncFinished = 0;
    new AsynchronCall( [ this, tmpWBT, tmpKlient, tmpSchrift ]()
    {
        Array< int > score;
        RCArray< Text > player;
        RCArray< Text > option;
        int anz = tmpKlient->getMinigameBestscoreList( "Bloecke", &score, &player, &option );
        for( int i = 0; i < anz; i++ )
        {
            TextFeld *scoreT = initTextFeld( 0, 0, 0, 0, tmpSchrift, TextFeld::Style::Text | TextFeld::Style::VCenter, Text( score.get( i ) ) );
            TextFeld *spielerT = initTextFeld( 0, 0, 0, 0, tmpSchrift, TextFeld::Style::Text | TextFeld::Style::VCenter, player.z( i )->getText() );
            Text optionen = option.z( i )->getText();
            Text *breite = optionen.getTeilText( optionen.positionVon( '=' ) + 1, optionen.positionVon( ',' ) );
            Text *h�he = optionen.getTeilText( optionen.positionVon( '=', 1 ) + 1, optionen.positionVon( ',', 1 ) );
            Text *farben = optionen.getTeilText( optionen.positionVon( '=', 2 ) + 1, optionen.positionVon( ',', 2 ) );
            Text *geschwindigkeit = optionen.getTeilText( optionen.positionVon( '=', 3 ) + 1 );
            TextFeld *breiteT = initTextFeld( 0, 0, 0, 0, tmpSchrift, TextFeld::Style::Text | TextFeld::Style::VCenter, breite->getText() );
            breite->release();
            TextFeld *h�heT = initTextFeld( 0, 0, 0, 0, tmpSchrift, TextFeld::Style::Text | TextFeld::Style::VCenter, h�he->getText() );
            h�he->release();
            TextFeld *farbenT = initTextFeld( 0, 0, 0, 0, tmpSchrift, TextFeld::Style::Text | TextFeld::Style::VCenter, farben->getText() );
            farben->release();
            TextFeld *geschwindigkeitT = initTextFeld( 0, 0, 0, 0, tmpSchrift, TextFeld::Style::Text | TextFeld::Style::VCenter, geschwindigkeit->getText() );
            geschwindigkeit->release();
            Knopf *ansehenK = initKnopf( 0, 0, 0, 0, tmpSchrift, Knopf::Style::Normal, "Ansehen" );
            ansehenK->setMausEreignis( [ this, optionen ]( void *p, void *obj, MausEreignis me ) -> bool
            {
                if( me.id == ME_RLinks && !me.verarbeitet )
                {
                    ( (Knopf*)obj )->removeStyle( Knopf::Style::Erlaubt );
                    getThis();
                    new AsynchronCall( [ this, optionen, obj ]()
                    {
                        Datei *d = klient->downloadGameCapture( "Bloecke", optionen );
                        ( (Knopf*)obj )->addStyle( Knopf::Style::Erlaubt );
                        if( wiederH )
                            wiederH = wiederH->release();
                        Text options = optionen.getText();
                        wiederH = new Men�Wiederhohlung( schrift, screen, d, &options );
                        release();
                    } );
                }
                return 1;
            } );
            tmpWBT->addZeile( optionen.getText() );
            tmpWBT->setZeichnungZ( 0, i + 1, scoreT );
            tmpWBT->setZeichnungZ( 1, i + 1, spielerT );
            tmpWBT->setZeichnungZ( 2, i + 1, ansehenK );
            tmpWBT->setZeichnungZ( 3, i + 1, breiteT );
            tmpWBT->setZeichnungZ( 4, i + 1, h�heT );
            tmpWBT->setZeichnungZ( 5, i + 1, farbenT );
            tmpWBT->setZeichnungZ( 6, i + 1, geschwindigkeitT );
        }
        tmpKlient->release();
        tmpWBT->release();
        tmpSchrift->release();
    }, &asyncFinished );
    InitDatei *opd = new InitDatei( "data/Minigames/Bl�cke/data/optionen.ini" );
    opd->laden();
    if( !opd->wertExistiert( "Breite" ) )
        opd->addWert( "Breite", "20" );
    if( !opd->wertExistiert( "Height" ) )
        opd->addWert( "Height", "12" );
    if( !opd->wertExistiert( "Farben" ) )
        opd->addWert( "Farben", "5" );
    if( !opd->wertExistiert( "Geschwindigkeit" ) )
        opd->addWert( "Geschwindigkeit", "4000" );
    if( !opd->wertExistiert( "Fortsetzen" ) )
        opd->addWert( "Fortsetzen", "0" );
    opd->speichern();
    KSGTDatei *stb = new KSGTDatei( "data/Minigames/Bl�cke/data/score.ksgt" );
    stb->laden();
    int anz = stb->getZeilenAnzahl();
    bool *fertig = new bool[ anz ];
    ZeroMemory( fertig, anz );
    int mS = 0;
    int omS = 0;
    int oAnz = 0;
    for( int i = 0; i < anz; i++ )
    {
        int maxScore = -1;
        int p = -1;
        for( int j = 0; j < anz; j++ )
        {
            if( !fertig[ j ] && maxScore < (int)*stb->zFeld( j, 1 ) )
            {
                p = j;
                maxScore = (int)*stb->zFeld( j, 1 );
            }
        }
        if( p >= 0 )
        {
            fertig[ p ] = 1;
            TextFeld *scoreT = initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text | TextFeld::Style::VCenter, stb->zFeld( p, 1 )->getText() );
            TextFeld *datumT = initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text | TextFeld::Style::VCenter, stb->zFeld( p, 0 )->getText() );
            TextFeld *breiteT = initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text | TextFeld::Style::VCenter, stb->zFeld( p, 2 )->getText() );
            TextFeld *h�heT = initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text | TextFeld::Style::VCenter, stb->zFeld( p, 3 )->getText() );
            TextFeld *farbenT = initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text | TextFeld::Style::VCenter, stb->zFeld( p, 5 )->getText() );
            TextFeld *tempoT = initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text | TextFeld::Style::VCenter, stb->zFeld( p, 4 )->getText() );
            gesammtT->addZeile( Text() += p );
            gesammtT->setZeichnungZ( 0, i + 1, scoreT );
            gesammtT->setZeichnungZ( 1, i + 1, datumT );
            gesammtT->setZeichnungZ( 2, i + 1, breiteT );
            gesammtT->setZeichnungZ( 3, i + 1, h�heT );
            gesammtT->setZeichnungZ( 4, i + 1, farbenT );
            gesammtT->setZeichnungZ( 5, i + 1, tempoT );
            if( breiteT->zText()->istGleich( opd->zWert( "Breite" )->getText() ) &&
                h�heT->zText()->istGleich( opd->zWert( "Height" )->getText() ) &&
                farbenT->zText()->istGleich( opd->zWert( "Farben" )->getText() ) &&
                tempoT->zText()->istGleich( opd->zWert( "Geschwindigkeit" )->getText() ) )
            {
                optionenT->addZeile( Text() += p );
                int n = optionenT->getZeilenNummer( Text() += p );
                optionenT->setZeichnungZ( 0, n, scoreT );
                optionenT->setZeichnungZ( 1, n, datumT );
                optionenT->setZeichnungZ( 2, n, breiteT );
                optionenT->setZeichnungZ( 3, n, h�heT );
                optionenT->setZeichnungZ( 4, n, farbenT );
                optionenT->setZeichnungZ( 5, n, tempoT );
                if( !omS )
                    omS = maxScore;
                oAnz++;
            }
        }
        if( !mS )
            mS = maxScore;
    }
    delete[] fertig;
    DiagDaten *gd = new DiagDaten();
    gd->style = DiagDaten::Style::autoIntervall | DiagDaten::Style::autoRaster | DiagDaten::Style::intervalle | DiagDaten::Style::intervallTexte | DiagDaten::Style::Sichtbar;
    gd->hIntervallFarbe = 0xFFFFFFFF;
    gd->hIntervallName->setText( "Spiel" );
    gd->rasterDicke = 1;
    gd->rasterFarbe = 0xFF505050;
    gd->vIntervallFarbe = 0xFFFFFFFF;
    gd->vIntervallName->setText( "Score" );
    gesammtD->setDiagDatenZ( gd );
    gesammtD->addVIntervallText( mS + 1, Text() += ( mS + 1 ) );
    gesammtD->addVIntervallText( 0, "0" );
    gesammtD->addHIntervallText( 0, "1" );
    if( anz > 1 )
        gesammtD->addHIntervallText( anz - 1, Text() += anz );
    gesammtD->addWert( "Score" );
    gesammtD->setWertStyle( 0, DiagWert::Style::Sichtbar | DiagWert::Style::Hintergrund );
    gesammtD->setWertFarbe( 0, 0xFF00FF00 );
    gesammtD->zDiagWert( 0 )->hintergrund = 0xFF205050;
    DiagDaten *od = new DiagDaten();
    od->style = DiagDaten::Style::autoIntervall | DiagDaten::Style::autoRaster | DiagDaten::Style::intervalle | DiagDaten::Style::intervallTexte | DiagDaten::Style::Sichtbar;
    od->hIntervallFarbe = 0xFFFFFFFF;
    od->hIntervallName->setText( "Spiel" );
    od->rasterDicke = 1;
    od->rasterFarbe = 0xFF505050;
    od->vIntervallFarbe = 0xFFFFFFFF;
    od->vIntervallName->setText( "Score" );
    optionenD->setDiagDatenZ( od );
    optionenD->addVIntervallText( omS + 1, Text() += ( omS + 1 ) );
    optionenD->addVIntervallText( 0, "0" );
    optionenD->addHIntervallText( 0, "1" );
    if( oAnz > 1 )
        optionenD->addHIntervallText( oAnz - 1, Text() += oAnz );
    optionenD->addWert( "Score" );
    optionenD->setWertStyle( 0, DiagWert::Style::Sichtbar | DiagWert::Style::Hintergrund );
    optionenD->setWertFarbe( 0, 0xFF00FF00 );
    optionenD->zDiagWert( 0 )->hintergrund = 0xFF205050;
    int j = 0;
    for( int i = 0; i < anz; i++ )
    {
        gesammtD->addPunkt( 0, i, (int)*stb->zFeld( i, 1 ) );
        if( (int)*stb->zFeld( i, 2 ) == (int)*opd->zWert( "Breite" ) &&
            (int)*stb->zFeld( i, 3 ) == (int)*opd->zWert( "Height" ) &&
            (int)*stb->zFeld( i, 5 ) == (int)*opd->zWert( "Farben" ) &&
            (int)*stb->zFeld( i, 4 ) == (int)*opd->zWert( "Geschwindigkeit" ) )
        {
            optionenD->addPunkt( 0, j, (int)*stb->zFeld( i, 1 ) );
            j++;
        }
    }
    stb->release();
    opd->release();
    beendet = 0;
}

void Men�Statistik::doMausEreignis( MausEreignis &me )
{
    if( wiederH )
    {
        wiederH->doMausEreignis( me );
        return;
    }
    ansicht->doMausEreignis( me );
    optionen->doMausEreignis( me );
    gesammtT->doMausEreignis( me );
    optionenT->doMausEreignis( me );
    worldBestT->doMausEreignis( me );
    bool vera = me.verarbeitet;
    removen->doMausEreignis( me );
    if( !vera && me.verarbeitet && me.id == ME_RLinks )
    { // Statistik removen
        if( optionen->hatStyle( KontrollKnopf::Style::Selected ) )
        { // nur bestimmte Statistik removen
            InitDatei *opd = new InitDatei( "data/Minigames/Bl�cke/data/optionen.ini" );
            opd->laden();
            KSGTDatei *score = new KSGTDatei( "data/Minigames/Bl�cke/data/score.ksgt" );
            score->laden();
            int zeilen = score->getZeilenAnzahl();
            for( int i = 0; i < zeilen; i++ )
            {
                if( (int)*score->zFeld( i, 2 ) == (int)*opd->zWert( "Breite" ) &&
                    (int)*score->zFeld( i, 3 ) == (int)*opd->zWert( "Height" ) &&
                    (int)*score->zFeld( i, 5 ) == (int)*opd->zWert( "Farben" ) &&
                    (int)*score->zFeld( i, 4 ) == (int)*opd->zWert( "Geschwindigkeit" ) )
                {
                    score->removeZeile( i );
                    i--;
                    zeilen--;
                }
            }
            score->speichern();
            score->release();
            opd->release();
        }
        else // alles removen
            DateiRemove( "data/Minigames/Bl�cke/data/score.ksgt" );
        reset();
    }
    vera = me.verarbeitet;
    zur�ck->doMausEreignis( me );
    if( !vera && me.verarbeitet && me.id == ME_RLinks )
        beendet = 1;
}

bool Men�Statistik::tick( double tickVal )
{
    if( wiederH )
    {
        bool ret = wiederH->tick( tickVal );
        if( wiederH->istBeendet() )
            wiederH = wiederH->release();
        return ret;
    }
    bool ret = ansicht->tick( tickVal );
    ret |= optionen->tick( tickVal );
    ret |= removen->tick( tickVal );
    ret |= zur�ck->tick( tickVal );
    ret |= gesammtT->tick( tickVal );
    ret |= optionenT->tick( tickVal );
    ret |= gesammtD->tick( tickVal );
    ret |= optionenD->tick( tickVal );
    ret |= worldBestT->tick( tickVal );
    return ret;
}

void Men�Statistik::render( Bild &zRObj )
{
    if( wiederH )
    {
        wiederH->render( zRObj );
        return;
    }
    tr->setSchriftSize( 12 );
    Text weltScore = "Welt Score:";
    tr->renderText( 10, 40, weltScore, zRObj, 0xFFFFFFFF );
    Text localScore = "Dein Score:";
    tr->renderText( 10, 170, localScore, zRObj, 0xFFFFFFFF );
    worldBestT->render( zRObj );
    if( !ansicht->getAuswahl() )
    {
        if( optionen->hatStyle( KontrollKnopf::Style::Selected ) )
            optionenT->render( zRObj );
        else
            gesammtT->render( zRObj );
    }
    else
    {
        if( optionen->hatStyle( KontrollKnopf::Style::Selected ) )
            optionenD->render( zRObj );
        else
            gesammtD->render( zRObj );
    }
    ansichtT->render( zRObj );
    ansicht->render( zRObj );
    optionen->render( zRObj );
    removen->render( zRObj );
    zur�ck->render( zRObj );
}

// constant
bool Men�Statistik::istBeendet() const
{
    return beendet;
}

bool Men�Statistik::istWiederhohlung() const
{
    return wiederH != 0;
}

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

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


// Inhalt der Men�Optionen aus Men�.h
// Konstruktor
Men�Optionen::Men�Optionen( Schrift *zSchrift, Bildschirm *zScreen )
{
    breiteT = initTextFeld( 310, 140, 130, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::VCenter, "Spielfeld Breite:" );
    breite = initTextFeld( 440, 140, 50, 20, zSchrift, TextFeld::Style::TextFeld, "" );
    breite->setTastaturEreignis( _nurNummernTE );
    h�heT = initTextFeld( 310, 180, 130, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::VCenter, "Spielfeld Height:" );
    h�he = initTextFeld( 440, 180, 50, 20, zSchrift, TextFeld::Style::TextFeld, "" );
    h�he->setTastaturEreignis( _nurNummernTE );
    bAnzahlT = initTextFeld( 310, 220, 130, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::VCenter, "Verschiedene Farben:" );
    bAnzahl = initTextFeld( 440, 220, 50, 20, zSchrift, TextFeld::Style::TextFeld, "" );
    bAnzahl->setTastaturEreignis( _nurNummernTE );
    tempoT = initTextFeld( 310, 260, 130, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::VCenter, "Zeit Abst�nde:" );
    tempo = initTextFeld( 440, 260, 50, 20, zSchrift, TextFeld::Style::TextFeld, "" );
    tempo->setTastaturEreignis( _nurNummernTE );
    fortsetzen = initKontrollKnopf( 310, 300, 180, 20, zSchrift, KontrollKnopf::Style::Normal, "Letztes Spiel fortsetzen" );
    fortsetzen->setMausEreignis( _ret1ME );
    abbrechen = initKnopf( 310, 340, 85, 20, zSchrift, Knopf::Style::Sichtbar, "Abbrechen" );
    ok = initKnopf( 405, 340, 85, 20, zSchrift, Knopf::Style::Sichtbar, "Ok" );
    beendet = 0;
    ref = 1;
}

// Destruktor
Men�Optionen::~Men�Optionen()
{
    breiteT->release();
    breite->release();
    h�heT->release();
    h�he->release();
    bAnzahlT->release();
    bAnzahl->release();
    tempoT->release();
    tempo->release();
    fortsetzen->release();
    abbrechen->release();
    ok->release();
}

// nicht constant
void Men�Optionen::reset()
{
    InitDatei *opd = new InitDatei( "data/Minigames/Bl�cke/data/optionen.ini" );
    if( !opd->laden() )
        DateiPfadErstellen( "data/Minigames/Bl�cke/data/optionen.ini" );
    breite->setText( "20" );
    if( opd->wertExistiert( "Breite" ) )
        breite->setText( Text() += (int)*opd->zWert( "Breite" ) );
    else
        opd->addWert( "Breite", "20" );
    h�he->setText( "12" );
    if( opd->wertExistiert( "Height" ) )
        h�he->setText( Text() += (int)*opd->zWert( "Height" ) );
    else
        opd->addWert( "Height", "12" );
    bAnzahl->setText( "5" );
    if( opd->wertExistiert( "Farben" ) )
        bAnzahl->setText( Text() += (int)*opd->zWert( "Farben" ) );
    else
        opd->addWert( "Farben", "5" );
    tempo->setText( "4000" );
    if( opd->wertExistiert( "Geschwindigkeit" ) )
        tempo->setText( Text() += (int)*opd->zWert( "Geschwindigkeit" ) );
    else
        opd->addWert( "Geschwindigkeit", "4000" );
    fortsetzen->removeStyle( KontrollKnopf::Style::Selected );
    if( opd->wertExistiert( "Fortsetzen" ) )
        fortsetzen->setStyle( KontrollKnopf::Style::Selected, (int)*opd->zWert( "Fortsetzen" ) != 0 );
    else
        opd->addWert( "Fortsetzen", "0" );
    beendet = 0;
    opd->speichern();
    opd->release();
}

void Men�Optionen::doMausEreignis( MausEreignis &me )
{
    breite->doMausEreignis( me );
    h�he->doMausEreignis( me );
    bAnzahl->doMausEreignis( me );
    tempo->doMausEreignis( me );
    fortsetzen->doMausEreignis( me );
    bool vera = me.verarbeitet;
    abbrechen->doMausEreignis( me );
    if( !vera && me.verarbeitet && me.id == ME_RLinks )
        beendet = 1;
    vera = me.verarbeitet;
    ok->doMausEreignis( me );
    if( !vera && me.verarbeitet && me.id == ME_RLinks )
    {
        InitDatei *opd = new InitDatei( "data/Minigames/Bl�cke/data/optionen.ini" );
        if( !opd->laden() )
            DateiPfadErstellen( "data/Minigames/Bl�cke/data/optionen.ini" );
        if( (int)*breite->zText() > 100 )
            breite->setText( "100" );
        if( (int)*breite->zText() < 10 )
            breite->setText( "10" );
        if( opd->wertExistiert( "Breite" ) )
            opd->setWert( "Breite", Text() += (int)*breite->zText() );
        else
            opd->addWert( "Breite", Text() += (int)*breite->zText() );
        if( (int)*h�he->zText() > 100 )
            h�he->setText( "100" );
        if( (int)*h�he->zText() < 10 )
            h�he->setText( "10" );
        if( opd->wertExistiert( "Height" ) )
            opd->setWert( "Height", Text() += (int)*h�he->zText() );
        else
            opd->addWert( "Height", Text() += (int)*h�he->zText() );
        if( (int)*bAnzahl->zText() > 10 )
            bAnzahl->setText( "10" );
        if( (int)*bAnzahl->zText() < 3 )
            bAnzahl->setText( "3" );
        if( opd->wertExistiert( "Farben" ) )
            opd->setWert( "Farben", Text() += (int)*bAnzahl->zText() );
        else
            opd->addWert( "Farben", Text() += (int)*bAnzahl->zText() );
        if( (int)*tempo->zText() < 100 )
            tempo->setText( "100" );
        if( opd->wertExistiert( "Geschwindigkeit" ) )
            opd->setWert( "Geschwindigkeit", Text() += (int)*tempo->zText() );
        else
            opd->addWert( "Geschwindigkeit", Text() += (int)*tempo->zText() );
        if( opd->wertExistiert( "Fortsetzen" ) )
            opd->setWert( "Fortsetzen", Text() += (int)fortsetzen->hatStyle( KontrollKnopf::Style::Selected ) );
        else
            opd->addWert( "Fortsetzen", Text() += (int)fortsetzen->hatStyle( KontrollKnopf::Style::Selected ) );
        opd->speichern();
        opd->release();
        beendet = 1;
    }
}

void Men�Optionen::doTastaturEreignis( TastaturEreignis &te )
{
    breite->doTastaturEreignis( te );
    h�he->doTastaturEreignis( te );
    bAnzahl->doTastaturEreignis( te );
    tempo->doTastaturEreignis( te );
}

bool Men�Optionen::tick( double tickVal )
{
    bool ret = breite->tick( tickVal );
    ret |= h�he->tick( tickVal );
    ret |= bAnzahl->tick( tickVal );
    ret |= tempo->tick( tickVal );
    ret |= fortsetzen->tick( tickVal );
    ret |= abbrechen->tick( tickVal );
    ret |= ok->tick( tickVal );
    return ret;
}

void Men�Optionen::render( Bild &zRObj )
{
    breiteT->render( zRObj );
    breite->render( zRObj );
    h�heT->render( zRObj );
    h�he->render( zRObj );
    bAnzahlT->render( zRObj );
    bAnzahl->render( zRObj );
    tempoT->render( zRObj );
    tempo->render( zRObj );
    fortsetzen->render( zRObj );
    abbrechen->render( zRObj );
    ok->render( zRObj );
}

// constant
bool Men�Optionen::istBeendet() const
{
    return beendet;
}

// Reference Counting
Men�Optionen *Men�Optionen::getThis()
{
    ref++;
    return this;
}

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


// Inhalt der Men� Klasse aus Men�.h
// Konstruktor
Men�::Men�( Schrift *zSchrift, Bildschirm *zScreen, KSGClient::MinigameServerClient *klient )
{
    spielen = initKnopf( 350, 180, 100, 20, zSchrift, Knopf::Style::Sichtbar, "Spielen" );
    spielenF = new Men�Spiel( zSchrift, zScreen, klient->getThis() );
    optionen = initKnopf( 350, 220, 100, 20, zSchrift, Knopf::Style::Sichtbar, "Optionen" );
    optionenF = new Men�Optionen( zSchrift, zScreen );
    statistik = initKnopf( 350, 260, 100, 20, zSchrift, Knopf::Style::Sichtbar, "Statistik" );
    statistikF = new Men�Statistik( zSchrift, zScreen, klient );
    beenden = initKnopf( 350, 300, 100, 20, zSchrift, Knopf::Style::Sichtbar, "Beenden" );
    ram = new LRahmen();
    ram->setFarbe( 0xFFFFFFFF );
    beendet = 0;
    status = 0;
    LTDBDatei *bgd = new LTDBDatei();
    bgd->setDatei( new Text( "data/Minigames/Bl�cke/bilder/hintergrund.ltdb" ) );
    bgd->leseDaten( 0 );
    hintergrund = bgd->laden( 0, new Text( "bg.jpg" ) );
    bgd->release();
    ref = 1;
}

// Destruktor
Men�::~Men�()
{
    spielen->release();
    spielenF->release();
    optionen->release();
    optionenF->release();
    statistik->release();
    statistikF->release();
    beenden->release();
    if( hintergrund )
        hintergrund->release();
    ram->release();
}

// nicht constant
void Men�::reset()
{
    status = 0;
    beendet = 0;
}

void Men�::doMausEreignis( MausEreignis &me )
{
    switch( status )
    {
    case 0:
        if( 1 )
        {
            bool vera = me.verarbeitet;
            spielen->doMausEreignis( me );
            if( !vera && me.verarbeitet && me.id == ME_RLinks )
            {
                spielenF->reset();
                status = 3;
            }
            vera = me.verarbeitet;
            optionen->doMausEreignis( me );
            if( !vera && me.verarbeitet && me.id == ME_RLinks )
            {
                optionenF->reset();
                status = 1;
            }
            vera = me.verarbeitet;
            statistik->doMausEreignis( me );
            if( !vera && me.verarbeitet && me.id == ME_RLinks )
            {
                statistikF->reset();
                status = 2;
            }
            vera = me.verarbeitet;
            beenden->doMausEreignis( me );
            if( !vera && me.verarbeitet && me.id == ME_RLinks )
                beendet = 1;
        }
        break;
    case 1:
        optionenF->doMausEreignis( me );
        break;
    case 2:
        statistikF->doMausEreignis( me );
        break;
    case 3:
        spielenF->doMausEreignis( me );
    }
}

void Men�::doTastaturEreignis( TastaturEreignis &te )
{
    if( status == 1 )
        optionenF->doTastaturEreignis( te );
    if( status == 3 )
        spielenF->doTastaturEreignis( te );
}

bool Men�::tick( double z )
{
    switch( status )
    {
    case 0:
        if( 1 )
        {
            bool ret = spielen->tick( z );
            ret |= statistik->tick( z );
            ret |= optionen->tick( z );
            ret |= beenden->tick( z );
            return ret;
        }
    case 1:
        if( optionenF->istBeendet() )
        {
            status = 0;
            return 1;
        }
        return optionenF->tick( z );
    case 2:
        if( statistikF->istBeendet() )
        {
            status = 0;
            return 1;
        }
        return statistikF->tick( z );
    case 3:
        if( spielenF->istBeendet() )
        {
            status = 0;
            return 1;
        }
        return spielenF->tick( z );
    }
    return 0;
}

void Men�::render( Bild &zRObj )
{
    if( status != 3 && ( status != 2 || !statistikF->istWiederhohlung() ) )
        zRObj.drawBild( 0, 0, hintergrund->getBreite(), hintergrund->getHeight(), *hintergrund );
    switch( status )
    {
    case 0:
        ram->setPosition( 300, 170 );
        ram->setSize( 200, 160 );
        zRObj.alphaRegion( ram->getX(), ram->getY(), ram->getBreite(), ram->getHeight(), 0xD0000000 );
        ram->render( zRObj );
        spielen->render( zRObj );
        statistik->render( zRObj );
        optionen->render( zRObj );
        beenden->render( zRObj );
        break;
    case 1:
        ram->setPosition( 300, 130 );
        ram->setSize( 200, 240 );
        zRObj.alphaRegion( ram->getX(), ram->getY(), ram->getBreite(), ram->getHeight(), 0xD0000000 );
        ram->render( zRObj );
        optionenF->render( zRObj );
        break;
    case 2:
        if( !statistikF->istWiederhohlung() )
            zRObj.alphaRegion( 0, 0, hintergrund->getBreite(), hintergrund->getHeight(), 0xD0000000 );
        statistikF->render( zRObj );
        break;
    case 3:
        spielenF->render( zRObj );
    }
}

// constant
bool Men�::istBeendet() const
{
    return beendet;
}

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

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