#pragma once

#include <Bildschirm.h>
#include <Kam3D.h>
#include <Thread.h>
#include <Welt3D.h>

#include "Dimension.h"
#include "FactoryClient.h"
#include "PlayerKam.h"

class World : public Framework::Thread
{
public:
    static World* INSTANCE;

private:
    Dimension* currentDimension;
    Framework::Welt3D* renderedWorld;
    Framework::Bildschirm3D* zScreenPtr;
    PlayerKam* kam;
    bool firstMessage;
    int ownEntityId;
    Framework::Model3D* currentTarget;
    Array<Punkt> subscriptions;
    FactoryClient* client;
    FactoryCraftModel* selectionModel;
    Critical subLock;
    Critical targetLock;
    float dayLightFactor;
    double time;
    double dayLength;
    double transitionLength;
    double nightLength;
    Framework::DXBuffer* fallbackVertexLightBuffer;

public:
    World(Framework::Bildschirm3D* zScreen, FactoryClient* client);
    ~World();
    void update(bool background);
    void onTick(double time);
    void setChunk(Chunk* chunk);
    void thread() override;

    Block* zBlockAt(Framework::Vec3<int> location) const;
    Block* getBlockAt(Framework::Vec3<int> location) const;
    Dimension* zDimension() const;
    void setVisibility(Entity* zEntity, bool visible);
    Framework::Punkt getChunkCenter(int x, int y) const;
    Entity* zEntity(int id) const;
    Entity* getEntity(int id) const;
    void removeEntity(int id);
    PlayerKam* zKamera() const;
    int getCurrentPlayerId() const;
    Entity* getCurrentPlayerEntity() const;
    void setTarget(Framework::Model3D* zTarget);
    void lockWorld();
    void unlockWorld();
    void onChunkAdded(Punkt pos);
    Chunk* zChunk(Punkt center);
    Framework::Model3D* getCurrentTarget() const;
    FactoryCraftModel* zSelectedEffectModel() const;
    FactoryClient* zClient() const;
    float getDayLightFactor() const;
    Framework::DXBuffer* zFallbackVertexLightBuffer();
};