#pragma once

#include <Array.h>
#include "Ereignis.h"
#include "Aktionen.h"

using namespace Framework;

class TriggerRun;
class Spiel;

class VarPointer
{
private:
    Variable *var;
    Text name;
    int ref;

public:
    VarPointer( const char *name, Variable *var );
    ~VarPointer();
    Text getName() const;
    void setVariable( Variable *var );
    Variable *getVariable() const;
    Variable *zVariable() const;
    operator Variable *( ) const;
    VarPointer *getThis();
    VarPointer *release();
};

class LocalMemory
{
private:
    RCArray< VarPointer > vars;
    int ref;

public:
    LocalMemory();
    ~LocalMemory();
    void setVar( const char *name, Variable *var );
    Variable *getVariable( const char *name );
    Variable *zVariable( const char *name );
    LocalMemory *getThis();
    LocalMemory *release();
};

class ProgramCounter
{
private:
    Array< int > current;
    int depth;
    int ref;

public:
    ProgramCounter();
    ~ProgramCounter();
    void stepIn();
    void count();
    void stepOut();
    Text getUniqueString() const;
    int currentPosition() const;
    ProgramCounter *getThis();
    ProgramCounter *release();
};

class Bedingung
{
private:
    Aktion *expression;
    int ref;

public:
    Bedingung( Aktion *expression );
    ~Bedingung();
    void setExpression( Aktion *expr );
    bool check( Spiel *zSpiel, Ereignis *zEreignis );
    Bedingung *getThis();
    Bedingung *release();
};

class Trigger : public Variable
{
private:
    int id;
    Text name;
    int ereignisAnzahl;
    EreignisTyp *ereignisse;
    RCArray< Bedingung > *bedingungen;
    RCArray< Aktion > *aktionen;
    int runCount;
    bool aktiv;

public:
    Trigger( int id, const char *name, int ereignisAnzahl, EreignisTyp *ereignisse, RCArray< Bedingung > *bedingungen, RCArray< Aktion > *aktionen );
    ~Trigger();
    void setAktiv( bool aktiv );
    bool hatEreignis( EreignisTyp typ ) const;
    int getAktionAnzahl() const;
    Aktion *zAktion( int index ) const;
    Aktion *getAktion( int index ) const;
    // return: 0, falls die bedingungen nicht erf�llt sind
    TriggerRun *runTrigger( Ereignis *e, Spiel *zSpiel );
    int getId() const;
    int getRuns() const;
    const char *getName() const;
    bool istAktiv() const;
};

class TriggerRun
{
private:
    Trigger *trigger;
    Ereignis *ereignis;
    Spiel *zSpiel;
    LocalMemory localMem;
    ProgramCounter counter;
    int programCounter;
    double waitCount;
    int ref;

public:
    TriggerRun( Trigger *trig, Ereignis *e, Spiel *zSpiel );
    ~TriggerRun();
    // gibt 0 zur�ck, wenn der Ausl�ser vollst�ndig durchgelaufen ist
    bool runNext( double t );
    Trigger *getTrigger() const;
    TriggerRun *getThis();
    TriggerRun *release();
};