#pragma once
#include <queue>
#include <unordered_set>
#include <vector>

#include "Deer/Memory.h"
#include "Deer/Voxel.h"
#include "DeerRender/Render/VertexArray.h"
#include "Deer/VoxelWorld.h"

namespace Deer {
	struct ChunkRender {
		Scope<VertexArray> solidVoxel;
		bool hasData = false;
	};

	struct SolidVoxelVertexData {
		uint16_t textureID = 0;
		uint8_t ambient_occlusion = 0;

		uint8_t xPos = 0;
		uint8_t yPos = 0;
		uint8_t zPos = 0;

		uint8_t a_light = 0;
		uint8_t r_light = 0;
		uint8_t g_light = 0;
		uint8_t b_light = 0;

		uint8_t normal = 0;

		uint8_t u = 0;
		uint8_t v = 0;

		SolidVoxelVertexData() = default;
	};

	class ChunkUpdateQueue {
	   public:
		// TODO: Add priority
		void addChunk(ChunkID);
		void reset();
		ChunkID pullChunk();
		bool hasChunk();

	   private:
		std::queue<ChunkID> m_updateOrder;
		std::unordered_set<ChunkID, ChunkIDHash> m_containingChunks;
	};

    namespace VoxelWorld {
        // Chunk render data
        extern Scope<ChunkRender[]> chunksRender;
        extern ChunkUpdateQueue chunkQueue;
    
        // Voxel creation data
        extern std::vector<uint32_t> indices;
        extern std::vector<SolidVoxelVertexData> vertexData;

		// Voxel temp light variables
        extern std::queue<VoxelCordinates> ambientLightPropagation;
        extern std::queue<VoxelCordinates> voxelLightPropagation;
        extern std::vector<VoxelCordinates> tmp_voxelLightSource;

		void clearRenderVars();
		void initializeRenderVars(const VoxelWorldProps& props);
    }
}  // namespace Deer