#include "client/render/loader/ModelLoader.h"

#include "blitz/misc/AssetsManager.h"
#include "blitz/misc/Log.h"
#include <assimp/Importer.hpp>	 // C++ importer interface
#include <assimp/postprocess.h>	 // Post processing flags
#include <assimp/scene.h>		 // Output data structure

#define VERTEX_SIZE 3

namespace blitz {
namespace ModelLoader {

std::unique_ptr<GL::VertexArray> LoadModel(const std::string& fileName) {
	DataBuffer fileData = utils::AssetsManager::GetAsset(fileName);

	// Create an instance of the Importer class
	Assimp::Importer importer;

	// And have it read the given file with some example postprocessing
	// Usually - if speed is not the most important aspect for you - you'll
	// probably to request more postprocessing than we do in this example.
	const aiScene* scene =
		importer.ReadFileFromMemory(fileData.data(), fileData.GetSize(), aiProcess_CalcTangentSpace | aiProcess_Triangulate);

	// If the import failed, report it
	if (nullptr == scene) {
		utils::LOGE("Failed to load model !");
		return nullptr;
	}

	aiMesh** meshes = scene->mMeshes;
	std::size_t numMeshes = scene->mNumMeshes;

	std::vector<float> positions;

	std::vector<unsigned int> indicies;

	for (std::size_t i = 0; i < numMeshes; ++i) {
		aiFace* faces = meshes[i]->mFaces;
		std::size_t faceNumber = meshes[i]->mNumFaces;

		for (std::size_t j = 0; j < faceNumber; j++) {
			std::size_t offset = indicies.size();
			std::size_t numIndices = faces[j].mNumIndices;
			indicies.resize(indicies.size() + numIndices);
			std::memcpy(indicies.data() + offset, faces[j].mIndices, numIndices * sizeof(unsigned int));
		}

		aiVector3D* vertecies = meshes[i]->mVertices;
		std::size_t vertNumber = meshes[i]->mNumVertices;

		for (std::size_t j = 0; j < vertNumber; j++) {
			positions.push_back(vertecies[j].x);
			positions.push_back(vertecies[j].y);
			positions.push_back(vertecies[j].z / 2.0);
		}
	}

	GL::VertexBuffer positionVBO(positions, VERTEX_SIZE);
	positionVBO.AddVertexAttribPointer(0, VERTEX_SIZE, 0);

	auto Vao = std::make_unique<GL::VertexArray>(GL::ElementBuffer{indicies});
	Vao->Bind();
	Vao->BindVertexBuffer(positionVBO);
	Vao->Unbind();

	return Vao;
}

}  // namespace ModelLoader
}  // namespace blitz
