#pragma once

#include "SpielKlasse.h"
#include "Variablen.h"
#include "Trigger.h"
#include "Bariere.h"
#include "Base.h"
#include "Drop.h"
#include "Geschoss.h"
#include "Umlenkung.h"
#include "Tunnel.h"
#include "Schiene.h"
#include "Schalter.h"
#include "Statistik.h"
#include "Reader.h"
#include <Critical.h>
#include <Datei.h>
#include <Random.h>
#include <Punkt.h>

class Statistik;
class StatistikV;

class Spiel : public SpielKlasse
{
private:
    bool isRunning;
    RandomGenerator randG;
    SSDatenbankV *psqldb;
    RCArray< SSKlientV > *zKlients;
    RCArray< VarPointer > variablen;
    RCArray< Spieler > spieler;
    RCArray< Team > teams;
    RCArray< Bariere > barieren;
    RCArray< Base > basen;
    RCArray< Drop > drops;
    RCArray< Gegenstand > items;
    RCArray< Geschoss > shots;
    RCArray< FeuerballTreffer > feuer;
    RCArray< Schalter > schalter;
    RCArray< Schiene > schienen;
    RCArray< Timer > timer;
    RCArray< Tunnel > tunnel;
    RCArray< Umlenkung > umlenkungen;
    RCArray< Trigger > trigger;
    RCArray< TriggerRun > triggerRuns;
    Array< int > *zAccounts;
    Statistik *stat;
    Text mapPfad;
    Critical c;
    Datei *log;
    Punkt mapSize;
    int nextId;
    bool ende;
    int spielerAnzahl;
    int spielId;
    int karteId;
    int gameTicks;
    bool pause;
    int ref;

public:
    // Konstruktor
    Spiel();
    // Destruktor
    ~Spiel();
    // nicht constant
    void setPSQLK( SSDatenbankV *psqldb ) override; // call 1
    void setSpielId( int id ) override; // call 2
    void setKarteId( int karteId ) override; // call 3
    void setTempPfad( char *pfad ) override; // call 3.5
    void setAccounts( int anzahl, Array< int > *zAccounts ) override; // call 4
    void setKlients( int anzahl, RCArray< SSKlientV > *zKlients ) override; // call 5
    void setSpielerNummern( int anzahl, Array< int > *spielerNummern ) override; // call 6
    void run() override; // call 7
    void klientOffline( int accountId ) override;
    void klientOnline( int accountId, SSKlientV *zKlient ) override;
    void nachricht( int accountId, int len, char *bytes ) override;
    void setMapSize( int width, int height );
    void setPausiert( bool pausiert );
    void tick( double zeit );
    void addVariable( const char *name, Variable *var );
    void setVariable( const char *name, Variable *var );
    void addTeam( Team *team );
    void addSpieler( Spieler *spieler );
    void addBariere( Bariere *bariere );
    void addBase( Base *base );
    void addDrop( Drop *drop );
    void addGegenstand( Gegenstand *gegenstand );
    void addGeschoss( Geschoss *geschoss );
    void addSchalter( Schalter *schalter );
    void addSchiene( Schiene *schiene );
    void addTimer( Timer *timer );
    void addTunnel( Tunnel *tunnel );
    void addUmlenkung( Umlenkung *umlenkung );
    void addTrigger( Trigger *trigger );
    void addTriggerRun( TriggerRun *tRun );
    void activateShalter( int id );
    void throwEvent( Ereignis *e );
    Variable *getVariable( const char *name ) const;
    Variable *zVariable( const char *name ) const;
    bool istPausiert() const;
    bool needEvent( EreignisTyp typ ) const;
    Team *getTeam( int id ) const;
    Spieler *getSpieler( int id ) const;
    Iterator< Spieler * > getSpieler() const;
    Iterator< Bariere * > getBarieren() const;
    Bariere *getBariere( int id ) const;
    Base *getBase( int id ) const;
    Drop *getDrop( int id ) const;
    Schalter *getSchalter( int id ) const;
    Schiene *getSchiene( int id ) const;
    Timer *getTimer( int id ) const;
    Tunnel *getTunnel( int id ) const;
    Umlenkung *getUmlenkung( int id ) const;
    Trigger *getTrigger( int id ) const;
    int getNextId();
    double getRand();
    int getTickCount() const;
    void setEnde( Team *zGewinner );
    // constant
    StatistikV *getStatistik() const override;
    // Reference Counting 
    SpielKlasse *getThis() override;
    SpielKlasse *release() override;
};