#include "WorldGenerator.h"
#include "StaticRegistry.h"
#include "Game.h"
#include "AddChunkUpdate.h"
#include "NoiseInterpolator.h"

using namespace Framework;

WorldGenerator::WorldGenerator( int seed )
    : Thread(),
    exit( 0 ),
    seed( seed )
{
    setName( "World Generator" );
    start();
}

WorldGenerator::~WorldGenerator()
{}

void WorldGenerator::thread()
{
    while( !exit )
    {
        cs.lock();
        Area next;
        bool hasNext = 0;
        if( requestQueue.getEintragAnzahl() > 0 )
        {
            next = requestQueue.get( 0 );
            requestQueue.remove( 0 );
            hasNext = 1;
        }
        cs.unlock();
        if( !hasNext )
        {
            sleep( 1 );
            continue;
        }
        Punkt start = Game::INSTANCE->getChunkCenter( next.startX, next.startY );
        Punkt end = Game::INSTANCE->getChunkCenter( next.endX, next.endY );
        int xDir = start.x > end.x ? -1 : 1;
        int yDir = start.y > end.y ? -1 : 1;
        for( int x = start.x; xDir < 0 ? x >= end.x : x <= end.x; x += CHUNK_SIZE * xDir )
        {
            for( int y = start.y; yDir < 0 ? y >= end.y : y <= end.y; y += CHUNK_SIZE * yDir )
            {
                if( !Game::INSTANCE->doesChunkExist( x, y, next.dimensionId ) )
                {
                    Chunk* generatedChunk = StaticRegistry<DimensionGenerator>::INSTANCE.zElement( next.dimensionId )->generateChunk( seed, x, y );
                    generatedChunk->removeUnusedBlocks();
                    Game::INSTANCE->requestWorldUpdate( new AddChunkUpdate( generatedChunk ) );
                }
            }
        }
    }
}

void WorldGenerator::requestGeneration( Area request )
{
    cs.lock();
    requestQueue.add( request );
    cs.unlock();
}

void WorldGenerator::exitAndWait()
{
    exit = 1;
    warteAufThread( 10000 );
    ende();
}

Framework::Either<Block*, int> WorldGenerator::generateSingleBlock( Framework::Vec3<int> location, int dimensionId )
{
    return StaticRegistry<DimensionGenerator>::INSTANCE.zElement( dimensionId )->generateBlock( seed, location );
}