#include "RenderThread.h"
#include "Bildschirm.h"
#include "Zeit.h"

#include <iostream>

using namespace Framework;

// Inhalt der RenderTh Klasse aus RenderThread.h
// Konstruktor 
RenderTh::RenderTh()
    : Thread(),
    stoppen( 0 ),
    bildschirm( 0 ),
    zeit( new ZeitMesser() ),
    renderTickZeit( 1 / 60 ),
    renderParameter( 0 ),
    tickParameter( 0 ),
    renderFunktion( 0 ),
    tickFunktion( 0 ),
    pause( 0 ),
    maxFps( 30 )
{}

// Destruktor 
RenderTh::~RenderTh()
{
    beenden();
    if( bildschirm )
        bildschirm->release();
    zeit->release();
}

// nicht constant 
void RenderTh::lock()
{
    cs.lock();
}

void RenderTh::unlock()
{
    cs.unlock();
}

void RenderTh::setBildschirm( Bildschirm *bildschirm ) // setzt den Bildschirm
{
    lock();
    if( this->bildschirm )
        this->bildschirm->release();
    this->bildschirm = bildschirm;
    unlock();
}

void RenderTh::thread() // Render Schleife
{
    int val = 0;
    double time = 0;
    zeit->messungStart();
    double ausgleich = 0;
    while( !stoppen )
    {
        lock();
        if( bildschirm && !pause )
        {
            if( renderFunktion )
                renderFunktion( renderParameter, this, bildschirm->zRenderBild() );
            bildschirm->render();
            val++;
            if( tickFunktion )
                tickFunktion( tickParameter, this, renderTickZeit );
            bildschirm->tick( renderTickZeit );
            time += renderTickZeit;
            unlock();
            if( time > 1 )
            {
                time -= 1;
                std::cout << "FPS: " << val << "\n";
                val = 0;
            }
        }
        else
        {
            unlock();
            Sleep( 100 );
        }
        ausgleich += 1.0 / maxFps - renderTickZeit;
        if( ausgleich > 0 )
            Sleep( (int)( ausgleich * 1000 ) );
        zeit->messungEnde();
        zeit->messungStart();
        renderTickZeit = zeit->getSekunden();
    }
    zeit->messungEnde();
}

void RenderTh::beginn() // beginnt rendering
{
    stoppen = 0;
    start();
}

void RenderTh::beenden() // beendet den Thread
{
    stoppen = 1;
    warteAufThread( 2000 );
    if( run )
        ende();
}

void RenderTh::setMaxFps( int fps ) // setzt die Anzahl der Bilder pro Sekunde
{
    maxFps = fps;
}

void RenderTh::setPause( bool p ) // Renderpause
{
    pause = p;
}

void RenderTh::setRenderFunktion( std::function< void( void *, void *, Bild * ) > rF ) // setzt die Rückruf Funktion beim Rendern
{
    renderFunktion = rF;
}

void RenderTh::setTickFunktion( std::function< void( void *, void *, double ) > tF ) // setzt die Rückruf Funktion beim Tick
{
    tickFunktion = tF;
}

void RenderTh::setRenderFunktionParameter( void *p ) // setzt den Parameter der Rückruf Funktion beim Rendern
{
    renderParameter = p;
}

void RenderTh::setTickFunktionParameter( void *p ) // setzt den Parameter der Rückruf Funktion beim Tick
{
    tickParameter = p;
}

// constant
Bildschirm *RenderTh::getBildschirm() const // gibt den Bildschirm zurück
{
    return bildschirm ? dynamic_cast<Bildschirm *>( bildschirm->getThis() ) : 0;
}

Bildschirm *RenderTh::zBildschirm() const
{
    return bildschirm;
}

double RenderTh::getRenderTickZeit() const // gibt die Zeit zurück, die zum Rendern und zum Tick benötigt wird
{
    return renderTickZeit;
}