class ResourcePack {
	constructor (data) {
		this.name = data.name;
		this.description = data.description;

		this.meta = data.meta;

		this.models = data.models || new global.Map();
		this.textures = data.textures || new global.Map();
		this.sounds = new global.Map();
	}
	static loadFromZIP (zipBuffer) {
		if (!zipBuffer) return Promise.reject(new Error("Missing argument zipBuffer. "));
		return new Promise(function (resolve, reject) {
			global.fflate.unzip(new Uint8Array(zipBuffer), {}, function (error, data) {
				if (error) return reject(error);
				if (!data["pack.json"]) return reject(new Error("pack.json not found in zip file. "));

				let packMeta;
				try {
					packMeta = JSON.parse(global.fflate.strFromU8(data["pack.json"]));
				} catch (err) {
					return reject(err);
				}

				var packData = readPackMeta(packMeta, data);

				packData.meta = packMeta;

				var resourceLoadings = [];

				resourceLoadings.push(loadU8Textures(packMeta, data).then(function (textureMap) {
					packData.textures = textureMap;
				}).catch(reject));

				resourceLoadings.push(loadU8Models(packMeta, data).then(function (modelMap) {
					packData.models = modelMap;
				}).catch(reject));

				Promise.all(resourceLoadings).then(function () {
					var resourcePack = new ResourcePack(packData);

					global.core.emit("resourcepack-load", resourcePack);

					resolve(resourcePack);
				}).catch(reject);
			});
		});
	}
}

var readPackMeta = function (packMeta, packArchive) {
	var pack = {
		"name": packMeta.name,
		"description": packMeta.description
	};

	return pack;
};

var loadU8Textures = function (packMeta, packData) {
	return new Promise(function (resolve, reject) {
		var textureMap = new global.Map();

		var textureLoadings = [];

		var textureMeta = packMeta.textures;

		for (var textureName in textureMeta) {
			if (textureMeta.hasOwnProperty(textureName)) {
				var textureData = textureMeta[textureName];

				if (textureData.path) {
					var splitPath = textureData.path.split(/[\/\.]+/g);

					var extension = splitPath[splitPath.length - 1].toLowerCase();
					if (extension == "jpg") extension = "jpeg";

					if ((["png", "jpeg", "webp", "gif", "apng", "avif"]).indexOf(extension) > -1) {
						var type = "image";
					} else if ((["mp4", "mkv", "ogg", "webm"]).indexOf(extension) > -1) {
						var type = "video";
					}

					var mimeType = type + "/" + extension;

					if (!packData[textureData.path]) reject(new Error("Texture doesn't exist at " + textureData.path + ". "));

					var textureBind = {
						"name": textureName
					};

					textureLoadings.push(new Promise((function(res, rej) {
						var imageData = packData[textureData.path];

						var imageBlob = new Blob([imageData.buffer], {"type": mimeType});

						var imageObjectURL = URL.createObjectURL(imageBlob);

						var texture = new global.three.Texture();
						var image = new global.Image();

						texture.minFilter = global.three.NearestFilter;
						texture.magFilter = global.three.NearestFilter;

						image.onload = (function () {
							texture.image = image;
							texture.needsUpdate = true;

							var data = {
								"map": texture
							};

							textureMap.set(this.name, data);

							res(data);
						}).bind(textureBind);

						image.src = imageObjectURL;
					}).bind(textureBind)));
				} else if (textureData.texture) {
					var data  = {

					};

					textureMap.set(textureName, data);

					textureLoadings.push(Promise.resolve(data));
				}
			}
		}

		Promise.all(textureLoadings).then(function (textures) {
			resolve(textureMap);
		}).catch(reject);
	});
};

var loadU8Models = function (packMeta, packData) {
	return new Promise(function (resolve, reject) {
		var modelMap = new global.Map();

		var modelLoadings = [];

		var modelMeta = packMeta.models;

		for (var modelName in modelMeta) {
			if (modelMeta.hasOwnProperty(modelName)) {
				var modelData = modelMeta[modelName];

				var modelString = global.fflate.strFromU8(packData[modelData.path]);

				var modelJSON = JSON.parse(modelString);

				modelMap.set(modelName, modelJSON);

				modelLoadings.push(Promise.resolve(modelJSON));
			}
		}

		Promise.all(modelLoadings).then(function (models) {
			resolve(modelMap);
		}).catch(reject);
	});
};

module.exports = {
	"ResourcePack": ResourcePack
};
