#pragma once
#include <cstdint>

#include "Deer/Path.h"
#include "DeerRender/Render/VertexArray.h"

#define SCENE_MAX_MESH_COUNT 1024

namespace Deer {
	// The real position is the axis divided by 256, the model precition is 1 / 256.0f
	struct VertexPosition {
		int16_t x;
		int16_t y;
		int16_t z;

		VertexPosition() = default;
		VertexPosition(int16_t _x, int16_t _y, int16_t _z)
		    : x(_x), y(_y), z(_z) {}
	};

	// Vertex normal is represented with a number fromn [-64,64], and then its
	// divided by 64 to know the decimal number
	struct VertexNormal {
		int8_t x = 0;
		int8_t y = 0;
		int8_t z = 0;

		VertexNormal() = default;
		VertexNormal(int8_t _x, int8_t _y, int8_t _z) : x(_x), y(_y), z(_z) {}
	};

	struct MeshData {
		uint16_t vertexCount = 0;
		VertexPosition* vertexPositionsData = nullptr;
		VertexNormal* vertexNormalData = nullptr;

		uint16_t indexCount = 0;
		uint16_t* indexData = nullptr;

		MeshData() = default;
		~MeshData() {
			delete[] vertexPositionsData;
			delete[] vertexNormalData;
			delete[] indexData;
		}
		MeshData(const MeshData&) = delete;
		MeshData& operator=(const MeshData&) = delete;

		void freeData() {
			delete[] vertexPositionsData;
			vertexPositionsData = nullptr;
			delete[] vertexNormalData;
			vertexNormalData = nullptr;
			delete[] indexData;
			indexData = nullptr;
			vertexCount = 0;
			indexCount = 0;
		}
	};

	namespace MeshManager {
		uint16_t loadModel(const Path&);
		uint16_t loadModel(const MeshData&, const Path&);
		VertexArray& getModel(uint16_t model_id);
		const Path& getModelName(uint16_t model_id);

		void unloadAllModels();
	}

	namespace DataStore {
		void saveModel(const MeshData&, const Path& name);
		void loadModel(MeshData&, const Path& name);

		void saveBinModel(const MeshData&, const Path& name);

		void createExampleMeshData();
	}  // namespace DataStore
}  // namespace Deer