let menusContainer = document.getElementById("menus");

var menus = {};

var shownMenus = [];

var makeMenu = function () {
	module.exports.menuData = {
		"main": {
			"elements": [
				{
					"type": "button",
					"label": global.locales.getRawString(global.currentLanguage, "menu.main.play.label"),
					"action": "open-menu",
					"action-args": ["play", 1]
				},
				{
					"type": "button",
					"label": global.locales.getRawString(global.currentLanguage, "menu.main.settings.label"),
					"action": "open-menu",
					"action-args": ["settings", 1]
				},
				{
					"type": "button",
					"label": global.locales.getRawString(global.currentLanguage, "menu.main.quit.label"),
					"action": "exit"
				}
			]
		},
		"play": {
			"elements": [
				{
					"type": "button",
					"label": global.locales.getRawString(global.currentLanguage, "menu.play.singleplayer.label"),
					"action": "open-menu",
					"action-args": ["gamesel", 2]
				}
			]
		},
		"ingame": {
			"elements": [
				{
					"type": "button",
					"label": "Resume",
					"action": "run",
					"runnable": function () {
						global.inputs[0].grab();

						hideMenus(0);
					}
				},
				{
					"type": "button",
					"label": "Quit",
					"action": "run",
					"runnable": global.quitGame
				}
			]
		},
		"gamesel": {
			"elements": [
				{
					"type": "text",
					"id": "worldnameinput",
					"placeholder": "New World",
					"value": "New World",
					"action": "run",
					"runnable": function (event) {
						var newGameButton = global.document.getElementById("newgamebutton");

						if (event.target.value.length < 1) {
							newGameButton.disabled = true;
						} else {
							newGameButton.disabled = false;
						}
					}
				},
				{
					"type": "button",
					"id": "newgamebutton",
					"label": global.locales.getRawString(global.currentLanguage, "play.singleplayer.newgamebutton.label"),
					"action": "run",
					"runnable": function () {
						var worldNameInputBox = global.document.getElementById("worldnameinput");

						var worldName = worldNameInputBox.value;

						if (worldName.length < 1) worldName = worldNameInputBox.placeholder;

						global.createWorld(worldName).then(function (world) {
							global.startGame(0, worldName);
							hideMenus(0);
						});
					}
				},
				{
					"type": "button",
					"id": "loadgamebutton",
					"label": global.locales.getRawString(global.currentLanguage, "play.singleplayer.loadgamebutton.label"),
					"action": "run",
					"runnable": function () {
						var fileSelector = document.createElement("input");
						fileSelector.type = "file";
						fileSelector.accept = "application/zip";

						fileSelector.click();

						fileSelector.onchange = function (event) {
							if (!this.files || !this.files[0]) return;

							this.files[0].arrayBuffer().then(function (buffer) {
								var fileU8 = new Uint8Array(buffer);

								global.openSave(fileU8).then(function (worldList) {
									for (var worldName in worldList) {
										if (worldList.hasOwnProperty(worldName)) {
											var world = worldList[worldName];

											global.worlds[worldName] = world;

											var menuEntry = {
												"type": "button",
												"label": global.locales.getFormattedString(
													global.currentLanguage,
													"play.singleplayer.openworld.label",
													{
														"WORLD_NAME": worldName
													}),
												"action": "run",
												"runnable": (function (event) {
													hideMenus(0);

													global.startGame(0, this);
												}).bind(worldName)
											};

											module.exports.menuData["gamesel"].elements.push(menuEntry);
										}
									}

									hideMenus(2);

									menus["gamesel"] = constructMenu("gamesel", module.exports.menuData["gamesel"]);

									showMenu("gamesel", 2);
								}).catch(function (error) {
									console.error(error);
								});
							}).catch(function (error) {
								console.error(error);
							});
							delete fileSelector;
						};
					}
				}
			]
		},
		"settings": {
			"elements": [
				{
					"type": "button",
					"label": global.locales.getRawString(global.currentLanguage, "menu.settings.user.label"),
					"action": "open-menu",
					"action-args": ["user-settings", 2]
				},
				{
					"type": "button",
					"label": global.locales.getRawString(global.currentLanguage, "menu.settings.video.label"),
					"action": "open-menu",
					"action-args": ["video-settings", 2]
				},
				{
					"type": "button",
					"label": global.locales.getRawString(global.currentLanguage, "menu.settings.audio.label"),
					"action": "open-menu",
					"action-args": ["audio-settings", 2]
				},
				{
					"type": "button",
					"label": global.locales.getRawString(global.currentLanguage, "menu.settings.input.label"),
					"action": "open-menu",
					"action-args": ["input-settings", 2]
				}
			]
		},
		"user-settings": {
			"elements": [
				// {
				// 	"type": "text",
				// 	"name": "username",
				// 	"label": "Username",
				// 	"placeholder": "Username"
				// },
				{
					"type": "button",
					"label": global.locales.getRawString(global.currentLanguage, "settings.user.login.label"),
					"action": "open-menu",
					"action-args": ["matrix-login", 3]
				}
			]
		},
		"matrix-login": {
			"expand": true,
			"elements": [
				{
					"type": "text",
					"name": "homeserver-url",
					"id": "homeserverinput",
					"label": global.locales.getRawString(global.currentLanguage, "settings.login.homeserver-url.label"),
					"placeholder": "https://matrix.org/",
					"action": "run",
					"runnable": function (event) {
						var isValidURL = (/http.?:\/\/.+/g).test(event.target.value);
						var isValidMXID = (/@.+:.+/g).test(global.document.getElementById("mxidinput").value);
						var isValidPass = global.document.getElementById("mxpassinput").value.length > 0;

						var loginButton = global.document.getElementById("mxloginbutton");

						if (isValidURL && isValidMXID && isValidPass) {
							loginButton.disabled = false;
						} else {
							loginButton.disabled = true;
						}
					}
				},
				{
					"type": "text",
					"name": "mxid",
					"id": "mxidinput",
					"label": global.locales.getRawString(global.currentLanguage, "settings.login.mxid.label"),
					"placeholder": global.locales.getRawString(global.currentLanguage, "settings.login.mxid.placeholder"),
					"action": "run",
					"runnable": function (event) {
						var isValidURL = (/http.?:\/\/.+/g).test(global.document.getElementById("homeserverinput").value);
						var isValidMXID = (/@.+:.+/g).test(event.target.value);
						var isValidPass = global.document.getElementById("mxpassinput").value.length > 0;

						var loginButton = global.document.getElementById("mxloginbutton");

						if (isValidURL && isValidMXID && isValidPass) {
							loginButton.disabled = false;
						} else {
							loginButton.disabled = true;
						}
					}
				},
				{
					"type": "password",
					"name": "password",
					"id": "mxpassinput",
					"label": global.locales.getRawString(global.currentLanguage, "settings.login.password.label"),
					"placeholder": global.locales.getRawString(global.currentLanguage, "settings.login.password.placeholder"),
					"action": "run",
					"runnable": function (event) {
						var isValidURL = (/http.?:\/\/.+/g).test(global.document.getElementById("homeserverinput").value);
						var isValidMXID = (/@.+:.+/g).test(global.document.getElementById("mxidinput").value);
						var isValidPass = event.target.value.length > 0;

						var loginButton = global.document.getElementById("mxloginbutton");

						if (isValidURL && isValidMXID && isValidPass) {
							loginButton.disabled = false;
						} else {
							loginButton.disabled = true;
						}
					}
				},
				{
					"type": "button",
					"id": "mxloginbutton",
					"label": global.locales.getRawString(global.currentLanguage, "settings.user.login.label"),
					"disabled": true,
					"action": "run",
					"runnable": async function (event) {
						event.target.disabled = true;

						var username = global.document.getElementById("mxidinput").value
							.substring(1)
							.split(":")[0];

						if (!("matrixClient" in global.core.modules["network"])) {
							var matrixClient = await global.core.modules["network"].initMatrixClient(
								global.document.getElementById("homeserverinput").value,
								global.document.getElementById("mxidinput").value
							);
						}
						global.core.modules["network"].loginToMatrix(
							username,
							global.document.getElementById("mxpassinput").value
						).then(function () {
							localStorage.setItem("matrix_baseurl", global.document.getElementById("homeserverinput").value);
							localStorage.setItem("matrix_mxid", global.document.getElementById("mxidinput").value);
							localStorage.setItem("matrix_is_connected", true);

							hideMenus(3);

							event.target.disabled = false;
						}).catch(function (error) {
							event.target.disabled = false;
						});
					}
				}
			]
		},
		"video-settings": {
			"expand": true,
			"elements": [
				{
					"type": "slider",
					"name": "fieldofview",
					"label": "Field of view",
					"value": 70,
					"minimum": 30,
					"maximum": 150,
					"step": 1,
					"change": function (event) {

					}
				}
			]
		},
		"audio-settings": {
			"expand": true,
			"elements": [
				{
					"type": "slider",
					"name": "mastervolume",
					"label": "Master volume",
					"value": 100,
					"minimum": 0,
					"maximum": 100,
					"step": 1,
					"change": function (event) {

					}
				}
			]
		}
	};

	for (var name in module.exports.menuData) {
		if (module.exports.menuData.hasOwnProperty(name)) {
			var menu = module.exports.menuData[name];

			menus[name] = constructMenu(name, menu);
		}
	}
};

var constructMenu = function (name, data) {
	var menuElement = document.createElement("div");
	menuElement.classList.add("menu");

	for (var e = 0; e < data.elements.length; e++) {
		var element = data.elements[e];
		let dom;

		switch (element.type) {
			case "button":
				dom = document.createElement("button");
				dom.innerText = element.label;
				if ("disabled" in element) dom.disabled = element.disabled;

				switch (element.action) {
					case "open-menu":
						dom.onclick = (function (event) {
							showMenu(...this["action-args"]);
						}).bind(element);
						break;
					case "run":
						dom.onclick = element.runnable;
						break;
					case "exit":
						dom.classList.add("closebutton");
						dom.onclick = closeGame;
						break;
					default:

				}
				break;
			case "text":
				dom = document.createElement("input");
				dom.type = "text";

				if (element.placeholder) dom.placeholder = element.placeholder;

				if ("action" in element) {
					switch (element.action) {
						case "run":
							dom.oninput = element.runnable;
							break;
						default:

					}
				}
				break;
			case "password":
				dom = document.createElement("input");
				dom.type = "password";

				if ("disabled" in element) dom.disabled = element.disabled;

				if (element.placeholder) dom.placeholder = element.placeholder;

				if ("action" in element) {
					switch (element.action) {
						case "run":
							dom.oninput = element.runnable;
							break;
						default:

					}
				}
				break;
			case "slider":
				dom = document.createElement("input");
				dom.type = "range";
				dom.name = element.name;

				if ("disabled" in element) dom.disabled = element.disabled;

				if (element.value) dom.value = element.value;
				if (element.minimum) dom.min = element.minimum;
				if (element.maximum) dom.max = element.maximum;
				if (element.step) dom.step = element.step;
				break;
			case "void":
				dom = document.createElement("div");
				dom.classList.add("void");
				break;
			default:

		}

		if (element.id) dom.id = element.id;

		if ((element.type != "button") && element.label) {
			domLabel = document.createElement("label");
			domLabel.htmlFor = element.name;
			domLabel.innerText = element.label;
			menuElement.appendChild(domLabel);

			dom.name = element.name;
			dom.label = domLabel;
		}

		menuElement.appendChild(dom);
	}

	return menuElement;
};

var showMenu = function (name, offset) {
	if (shownMenus.length > 0 && (!shownMenus[offset - 1])) return;

	if (shownMenus[offset] == menus[name]) {
		return hideMenus(offset);
	} else {
		hideMenus(offset);

		var displayOffset = 0;

		for (var m = 0; m < shownMenus.length; m++) {
			displayOffset += shownMenus[m].clientWidth;
		}

		menus[name].style.left = displayOffset + "px";
		if (module.exports.menuData[name].expand) {
			menus[name].style.width = "calc(" + menusContainer.clientWidth + "px - " + (menusContainer.clientWidth - displayOffset) + "px)";
		} else {
			menus[name].style.width = "" + 16 + "rem";
		}
		menusContainer.appendChild(menus[name]);
		shownMenus.push(menus[name]);
	}
};

var hideMenus = function (offset) {
	for (var m = shownMenus.length; m >= offset; --m) {
		if (shownMenus[m]) menusContainer.removeChild(shownMenus[m]);
	}

	shownMenus.splice(offset, shownMenus.length - offset);
};

module.exports = {
	"menus": menus,
	"makeMenu": makeMenu,
	"constructMenu": constructMenu,
	"showMenu": showMenu,
	"hideMenus": hideMenus
};
