#pragma once

#include "render/Renderer.h"
#include "render/TextureManager.h"
#include <vector>
#include <chrono>
#include <iostream>
#include <string>
#include <array>
#include <numeric>
#include <random>
#include <algorithm>
#include <map>
#include <set>
#include "utils/Perlin.h"
#include "PlanetData.h"
#include "StoneObject.h"
#include "render/FrameBuffer.h"
#include <queue>
#include <mutex>

namespace ZL {
    class TaskManager;
    class MainThreadHandler;

    class PlanetObject {
    public:
        PlanetData planetData;

        // Данные только для рендеринга (OpenGL specific)
        VertexRenderStruct planetRenderStruct;
        VertexRenderStruct planetAtmosphereRenderStruct;
        StoneGroup planetStones;
        std::vector<VertexRenderStruct> stonesToRender;
        VertexRenderStruct stoneToBake;

        std::vector<int> triangleIndicesToDraw;

        std::shared_ptr<Texture> sandTexture;
        std::shared_ptr<Texture> stoneTexture;

        std::unique_ptr<FrameBuffer> stoneMapFB;


        VertexRenderStruct campPlatform;
        std::shared_ptr<Texture> campPlatformTexture;

        Vector3f lastUpdatePos;

        // External items, set outside
        Renderer& renderer;
        TaskManager& taskManager;
        MainThreadHandler& mainThreadHandler;
    public:
        PlanetObject(Renderer& iRenderer, TaskManager& iTaskManager, MainThreadHandler& iMainThreadHandler);

        void init();
        void update(float deltaTimeMs);
        void bakeStoneTexture(Renderer& renderer);
        void draw(Renderer& renderer);
        void drawStones(Renderer& renderer);
        void drawPlanet(Renderer& renderer);
        void drawAtmosphere(Renderer& renderer);
        void drawCamp(Renderer& renderer);

        float distanceToPlanetSurface(const Vector3f& viewerPosition);
    };

} // namespace ZL