#include "DeerRender/DataStore.h"
#include "DeerRender/Log.h"
#include "DeerRender/Mesh.h"
#include "DeerRender/Render/VertexArray.h"
#include "DeerRender/Tools/Memory.h"

#include "cereal/archives/json.hpp"
#include "cereal/cereal.hpp"

namespace Deer {
	VertexArray* loadModelToGPU(const MeshData& data);

	Scope<GPUMesh> ResourceBuilder<GPUMesh>::buildResource(const BaseDataType& base) {
		const MeshData& baseMeshData = base;

		Scope<GPUMesh> gpuMesh = MakeScope<GPUMesh>();
		gpuMesh->vertexArray = Scope<VertexArray>(loadModelToGPU(baseMeshData));

		return gpuMesh;
	}

	VertexArray* loadModelToGPU(const MeshData& data) {
		VertexArray* vertexArray = VertexArray::create();
		vertexArray->bind();

		BufferLayout positionLayout({{"v_position", DataType::Float3, ShaderDataType::FloatingPoint}}, sizeof(VertexPosition)); //
		Ref<VertexBuffer> vertexPositionBuffer = VertexBuffer::create(data.getVertexPosition(), data.getVertexCount() * sizeof(VertexPosition));
		vertexPositionBuffer->bind();
		vertexPositionBuffer->setLayout(positionLayout);
		vertexArray->addVertexBuffer(vertexPositionBuffer);

		BufferLayout normalLayout({{"v_normal", DataType::Byte3, ShaderDataType::NormalizedFloatingPoint}}, sizeof(VertexNormal));
		Ref<VertexBuffer> vertexNormalBuffer = VertexBuffer::create(data.getVertexNormal(), data.getVertexCount() * sizeof(VertexNormal));
		vertexNormalBuffer->bind();
		vertexNormalBuffer->setLayout(normalLayout);
		vertexArray->addVertexBuffer(vertexNormalBuffer);

		if (data.getVertexPosition()) {
			BufferLayout uvLayout({{"v_UV", DataType::Float2, ShaderDataType::FloatingPoint}}, sizeof(VertexUV));
			Ref<VertexBuffer> vertexUVBuffer = VertexBuffer::create(data.getVertexUV(), data.getVertexCount() * sizeof(VertexUV));
			vertexUVBuffer->bind();
			vertexUVBuffer->setLayout(uvLayout);
			vertexArray->addVertexBuffer(vertexUVBuffer);
		}

		Ref<IndexBuffer> indexBuffer = IndexBuffer::create(data.getIndexData(), data.getIndexCount() * sizeof(uint32_t), IndexDataType::Unsigned_Int);
		indexBuffer->bind();
		vertexArray->setIndexBuffer(indexBuffer);

		return vertexArray;
	}
} // namespace Deer