#ifndef RenderThread_H
#define RenderThread_H

#include <functional>

#include "Critical.h"
#include "Thread.h"

namespace Framework
{
    class Bildschirm; //! Bildschirm.h
    class ZeitMesser; //! ZeitMesser.h
    class Bild;       //! Bild.h

    //! Ein Thread, der ein Bildschirm verwaltet. Er ruft die render() und
    //! tick() funktionen automatisch auf
    class RenderTh : public Thread
    {
    private:
        bool stoppen;
        Bildschirm* bildschirm;
        ZeitMesser* zeit;
        double renderTickZeit;
        void* renderParameter;
        void* tickParameter;
        std::function<void(void*, void*, Bild*)> renderFunktion;
        std::function<void(void*, void*, double)> tickFunktion;
        bool pause;
        Critical cs;
        int maxFps;
        bool quiet;

    public:
        //! Konstruktor
        DLLEXPORT RenderTh();
        //! Destruktor
        DLLEXPORT ~RenderTh();
        //! Dies ist notwendig, falls mehrere Threads gleichzeitig das Objekt
        //! benutzen. Wenn lock() von zwei threads aufgerufen wird, wartet der
        //! letzte so lange, bis der erste unlock() aufgerufen hat.
        DLLEXPORT void lock();
        //! Dies ist notwendig, falls mehrere Threads gleichzeitig das Objekt
        //! benutzen. Wenn lock() von zwei threads aufgerufen wird, wartet der
        //! letzte so lange, bis der erste unlock() aufgerufen hat.
        DLLEXPORT void unlock();
        //! Setzt das Bildschirm Objekt, das verwaltet werden soll
        //! \param bildschirm Der Bildschirm
        DLLEXPORT void setBildschirm(Bildschirm* bildschirm);
        //! Die Funktion, die automatisch in einem neuen Thread ausgef�hrt wird
        DLLEXPORT void thread() override;
        //! Beginnt den Render Thread
        DLLEXPORT void beginn();
        //! Beendet den Render Thread
        DLLEXPORT void beenden();
        //! if true, then nothing will be printent to std::cout
        DLLEXPORT void setQuiet(bool quiet);
        //! Setzt die maximalen Bilder pro Sekunde
        //! \param fps maximale Bilder pro Sekunde
        DLLEXPORT void setMaxFps(int fps);
        //! Pausiert den Render Thread
        //! \param p 1, wenn der Thread pausiert werden soll
        DLLEXPORT void setPause(bool p);
        //! Setzt die R�ckruffunktion, die immer vor dem Zeichnen aufgerufen
        //! wird \param rF Die R�ckruffunktion
        DLLEXPORT void setRenderFunktion(
            std::function<void(void*, void*, Bild*)> rF);
        //! Setzt die R�ckruffunktion, die immer vor dem Aktualisieren aller
        //! Objekte aufgerufen wird \param tF Die R�ckruffunktion
        DLLEXPORT void setTickFunktion(
            std::function<void(void*, void*, double)> tF);
        //! Setzt den Parameter der R�ckruffunktion, die immer vor dem Zeichnen
        //! aufgerufen wird \param p Der Parameter
        DLLEXPORT void setRenderFunktionParameter(void* p);
        //! Setzt den Parameter der R�ckruffunktion, die immer vor dem
        //! Aktualisieren aller Objekte aufgerufen wird
        DLLEXPORT void setTickFunktionParameter(void* p);
        //! Gibt den Bildschirm zur�ck, der von dem Thread verwaltet wird
        DLLEXPORT Bildschirm* getBildschirm() const;
        //! Gibt den Bildschirm ohne erh�hten Reference Counter zur�ck, der von
        //! dem Thread verwaltet wird
        DLLEXPORT Bildschirm* zBildschirm() const;
        //! Gibt die Zeit zur�ck, mit der die tick() Funktion des Bildschirms
        //! als letztes aufgerufen wurde
        DLLEXPORT double getRenderTickZeit() const;
    };
} // namespace Framework

#endif