#include "Kamera2D.h"
#include "Welt2D.h"
#include "Bild.h"
#include "Globals.h"

using namespace Framework;


Kamera2D::Kamera2D()
    : ZeichnungHintergrund()
{
    setStyle( Style::Sichtbar );
    welt = 0;
    rotation = 0;
    matrix = Mat3< float >::identity();
    zoom = 1;
    tickWelt = 0;
    name = new Text( "" );
}

Kamera2D::~Kamera2D()
{
    if( welt )
        welt->release();
    name->release();
}

void Kamera2D::setName( const char *name )
{
    this->name->setText( name );
}

void Kamera2D::setName( Text *name )
{
    this->name->setText( name );
}

void Kamera2D::lookAtWorldPos( float x, float y )
{
    rend |= wPos != Vertex( x, y );
    wPos.x = x;
    wPos.y = y;
    if( welt && welt->getWorldInfo().hasSize && welt->getWorldInfo().circular )
    {
        if( wPos.x < 0 )
            wPos.x += (float)welt->getWorldInfo().size.x;
        if( wPos.y < 0 )
            wPos.y += (float)welt->getWorldInfo().size.y;
        if( wPos.x > ( float )welt->getWorldInfo().size.x )
            wPos.x -= (float)welt->getWorldInfo().size.x;
        if( wPos.y > ( float )welt->getWorldInfo().size.y )
            wPos.y -= (float)welt->getWorldInfo().size.y;
    }
}

void Kamera2D::lookAtWorldPos( Vertex pos )
{
    lookAtWorldPos( pos.x, pos.y );
}

void Kamera2D::lookAtWorldArea( float width, float height )
{
    zoom = (float)getBreite() / width;
    // TODO have two scaling factors
}

void Kamera2D::setDrehung( float rotation )
{
    rend |= this->rotation != rotation;
    this->rotation = rotation;
}

void Kamera2D::setZoom( float zoom )
{
    rend |= this->zoom != zoom;
    this->zoom = zoom;
}

void Kamera2D::setWelt( Welt2D *welt, bool tick )
{
    if( this->welt )
        this->welt->release();
    this->welt = welt;
    tickWelt = tick;
    rend = 1;
}

bool Kamera2D::tick( double time )
{
    if( welt && tickWelt )
        rend |= welt->tick( time );
    return ZeichnungHintergrund::tick( time );
}

void Kamera2D::render( Bild &zRObj )
{
    if( hatStyleNicht( Style::Sichtbar ) )
        return;
    ZeichnungHintergrund::render( zRObj );
    if( !welt )
        return;
    lockZeichnung();
    if( !zRObj.setDrawOptions( innenPosition, innenSize ) )
    {
        unlockZeichnung();
        return;
    }
    matrix = Mat3< float >::translation( (Vertex)gr / 2 ) * Mat3< float >::rotation( rotation ) * Mat3< float >::scaling( zoom ) * Mat3< float >::translation( -wPos );
    welt->render( matrix, gr, zRObj, *name );
    zRObj.releaseDrawOptions();
    unlockZeichnung();
}

Vertex Kamera2D::getWorldCoordinates( Punkt screenPos )
{
    Vertex wKoord = ( Mat3< float >::translation( wPos ) * Mat3< float >::scaling( 1 / zoom ) * Mat3< float >::rotation( -rotation ) * Mat3< float >::translation( (Vertex)gr / -2 ) ) * (Vertex)screenPos;
    if( welt->getWorldInfo().circular && welt->getWorldInfo().hasSize && welt->getWorldInfo().size.x && welt->getWorldInfo().size.y )
    {
        while( wKoord.x < 0 )
            wKoord.x += (float)welt->getWorldInfo().size.x;
        while( wKoord.x > ( float )welt->getWorldInfo().size.x )
            wKoord.x -= (float)welt->getWorldInfo().size.x;
        while( wKoord.y < 0 )
            wKoord.y += (float)welt->getWorldInfo().size.y;
        while( wKoord.y > ( float )welt->getWorldInfo().size.y )
            wKoord.y -= (float)welt->getWorldInfo().size.y;
    }
    return wKoord;
}

Vertex Kamera2D::getWorldDirection( Vertex dir )
{
    return Vertex( dir.x, dir.y ).rotation( -rotation ) * ( 1 / zoom );
}

Vertex Kamera2D::getWorldPosition()
{
    return wPos;
}

float Kamera2D::getRotation()
{
    return rotation;
}

float Kamera2D::getZoom()
{
    return zoom;
}

const Mat3< float > &Kamera2D::getMatrix()
{
    return matrix;
}

Text *Kamera2D::getName()
{
    return dynamic_cast<Text *>( name->getThis() );
}

Text *Kamera2D::zName()
{
    return name;
}

bool TestKamera2D::tick( double time )
{
    bool ret = rend;
    rend = Kamera2D::tick( time );
    if( getTastenStand( 'q' ) )
    {
        rotation += (float)( time * 0.5 );
        ret = 1;
    }
    if( getTastenStand( 'e' ) )
    {
        rotation -= (float)( time * 0.5 );
        ret = 1;
    }
    Vertex move;
    if( getTastenStand( 'w' ) )
        move = Vertex( 0, -100 * (float)time );
    if( getTastenStand( 'a' ) )
        move = Vertex( -100 * (float)time, 0 );
    if( getTastenStand( 'd' ) )
        move = Vertex( 100 * (float)time, 0 );
    if( getTastenStand( 's' ) )
        move = Vertex( 0, +100 * (float)time );
    if( move != Vertex( 0, 0 ) )
    {
        wPos += move.rotation( -rotation ) * ( 1 / zoom );
        ret = 1;
    }
    if( getTastenStand( '+' ) )
    {
        zoom += ( zoom ) * (float)time;
        ret = 1;
    }
    if( getTastenStand( '-' ) )
    {
        zoom -= ( zoom ) * (float)time;
        if( zoom <= 0 )
            zoom = 1;
        ret = 1;
    }
    return ret;
}