"use strict";
/*jshint esversion: 6 */
/*jshint multistr: true */

var PAGES = ["pageInfos", "pageSource", "pageMfd1", "pageMfd2"];
var pagePos = [ 0, 0, 0, 0, 0 ];
var ANIMATION_INTERVAL = 25;
var FEEDBACK_DURATION = 500;
var PAGE_TRANSITION = 500;
var SWIPE_DELAY = 250
var SWIPE_DIST = 100
var pageIndex = 0;
var touchStartX = -1;
var touchStartY = -1;
var touchStartTime = -1;


function displayCheck(id) {
	let link = document.getElementById(id);
	link.setAttribute("class", "mu check");
	setTimeout(() => link.setAttribute("class", "mu"), FEEDBACK_DURATION);
}


function doDisplay() {
	let diagram = source.Mocodo.load(document.getElementById("source").value + "\n");
	let mfd1 = getOptionValue("mfd1");
	document.getElementById("mfd1title").innerHTML = mfd1;
	let mfd2 = getOptionValue("mfd2");
	document.getElementById("mfd2title").innerHTML = mfd2;
	if (diagram != null) {
		let mld = transform.DiagramToMLD.transform(diagram);
		transform.DiagramToUML.transform(diagram);
		document.getElementById("mfd1").innerHTML = generateContent(diagram, mld, mfd1);
		document.getElementById("mfd2").innerHTML = generateContent(diagram, mld, mfd2);
	} else {
		document.getElementById("mfd1").innerHTML = "";
		document.getElementById("mfd2").innerHTML = "";
	}
}


function download(filename, content) {
	let a = document.createElement("a");
	a.setAttribute("href", content);
	a.setAttribute("download", filename);
	a.style.display = "none";
	document.getElementById("body").appendChild(a);
	a.click();
	document.getElementById("body").removeChild(a);
}


function generateContent(diagram, mld, opt) {
	let content = "";
	if (opt == "MCD" || opt == "Tables" || opt.substr(0,3) == "UML") {
		if (opt == "MCD") content = schema.MCDToSVG.generateSVG(diagram).toString();
		else if (opt == "UML-Domaine") content = schema.UMLToSVG.generateSVG(diagram, false, true).toString();
		else if (opt == "UML-Classes") content = schema.UMLToSVG.generateSVG(diagram, true, true).toString();
		else if (opt == "UML-API") content = schema.UMLToSVG.generateSVG(diagram, true, false).toString();
		else content = schema.MLDToSVG.generateSVG(mld, true).toString(); //Tables
	}
	else if (opt == "MR-EN") content = "<pre>" + mld.toString(false) + "</pre>";
	else if (opt == "MR-Univ") {
		content = "<pre>" + mld.toString(true) + "</pre>";
		content = content.replaceAll("\x1B[4m", '<span style="text-decoration:underline">');
		content = content.replaceAll("\x1B[1m", '<span style="font-weight:bold">');
		content = content.replaceAll("\x1B[0m", "</span>");
	} else if (opt == "MLD") content = schema.MLDToSVG.generateSVG(mld, false).toString();
	else if (opt == "SQL-MariaDB" || opt == "SQL-PostgreSQL" || opt == "SQL-Sqlite") {
		let sql = null;
		switch (opt) {
			case "SQL-MariaDB": sql = database.DBMariaDB.generateSQL(mld); break;
			case "SQL-PostgreSQL": sql = database.DBPostgreSQL.generateSQL(mld); break;
			case "SQL-Sqlite": sql = database.DBSqlite.generateSQL(mld); break;
		}
		let sqlfmt = "";
		for (let line of sql.split("\n")) {
			if (line.indexOf("CREATE") == 0) {
				sqlfmt += line.replaceAll(", ", ",\n    ").replace(" (", " (\n    ").replace(");", "\n);\n\n");
			} else {
				sqlfmt += line + "\n\n";
			}
		}
		sqlfmt = sqlfmt.substring(0, sqlfmt.length - 3);
		content = "<pre>" + sqlfmt + "</pre>";
	} else if (opt == "Haxe" || opt == "Java" || opt == "PHP" || opt == "Python") {
		let files = null; //files is a haxe.ds.StringMap
		switch (opt) {
			case "Haxe" : files = code.HaxeCode.generate(diagram); break;
			case "Java" : files = code.JavaCode.generate(diagram); break;
			case "PHP" : files = code.PhpCode.generate(diagram); break;
			case "Python" : files = code.PythonCode.generate(diagram); break;
		}
		content = "<div>";
		for (let fileName in files.h) { //files.h -> javascript dictionnary
			content += "<h3>" + fileName + "</h3>" + "<pre>" + files.h[fileName].replace(/</g, "&lt;") + "</pre>";
		}
		content += "</div>";
	}
	return content;
}


function getContent(id, forceText = false) {
	let content = "";
	let zone = document.getElementById(id);
	if (zone.nodeName.toUpperCase() == "TEXTAREA") content = zone.value;
	else if (zone.firstChild.nodeName.toUpperCase() == "SVG") {
		content = zone.innerHTML;
	} else {
		if (zone.firstChild.nodeName.toUpperCase() == "PRE") {
			if (forceText) {
				content = zone.firstChild.innerHTML;
				content = content.replaceAll('<span style="text-decoration:underline">', "\x1B[4m");
				content = content.replaceAll('<span style="font-weight:bold">', "\x1B[1m");
				content = content.replaceAll("</span>", "\x1B[0m");
			} else {
				content = zone.innerHTML; //keep <pre>
			}
		} else {
			content = forceText ? zone.firstChild.innerText : zone.firstChild.innerHTML;
		}
	}
	return content;
}


function getFilename(id, filename) {
	let zone = document.getElementById(id);
	if (zone.nodeName.toUpperCase() == "TEXTAREA") {
		if (filename.indexOf(".") == -1) {
			filename += ".dbc";
		}
	} else if (zone.firstChild.nodeName.toUpperCase() == "PRE") {
		if (getOptionValue(id).indexOf("SQL") != -1) {
			if (!filename.endsWith(".sql")) {
				filename += ".sql";
			}
		} else { //MR-EN/Univ
			if (filename.indexOf(".") == -1) {
				filename += ".txt";
			}
		}
	} else if (zone.firstChild.nodeName.toUpperCase() == "SVG") {
		if (!filename.endsWith(".svg")) {
			filename += ".svg";
		}
	} else if (zone.firstChild.nodeName.toUpperCase() == "DIV") {
		if (!filename.endsWith(".zip")) {
			filename += ".zip";
		}
	}
	return filename;
}


function getMimeType(id) {
	let mimeType = "text/plain";
	let zone = document.getElementById(id);
	
	if (zone.childNodes.length != 0 && zone.firstChild.nodeName.toUpperCase() == "SVG") {
		mimeType = "image/svg+xml";
	} else if (getOptionValue(id).indexOf("SQL") != -1) {
		mimeType = "application/sql";
	}
	return mimeType;
}


function getOptionValue(group) {
	let value = "";
	let items = document.getElementsByName(group);
	for (let i = 0; i < items.length; i++) {
		if (items[i].checked) {
			value = items[i].value;
			break;
		}
	}
	return value;
}



function loadExample(example, mfd1, mfd2) {
	let source = "";
	if (example == "evaluation") {
		source = ":\n\
Personne: id [COUNTER], nom, prenom\n\
/XT\\ Personne - Étudiant, Professeur\n\
\n\
Étudiant: classe\n\
:\n\
Professeur: matière\n\
\n\
Évaluation, 0N Étudiant, 0N Devoir: note [FLOAT]\n\
:\n\
Évaluer, 0N> Professeur, 11 Évaluation\n\
\n\
Devoir: id [COUNTER], dateDevoir [DATE], titre";
	} else if (example == "facturation") {
		source = "Commande: idCommande [COUNTER], dateCommande [DATE]\n\
Commander, 0N Client, 11 Commande\n\
Client: idClient [COUNTER], nom, prénom, rue, ville, code postal [CHAR(5)]\n\
\n\
Comprendre, 0N Commande, _11 LigneCommande\n\
:\n\
Parrainer, 0N> [parrain] Client, 01 Client\n\
\n\
LigneCommande: noLigne [INT], qte [INT], prixAchat [FLOAT]\n\
Concerner, 11 LigneCommande, 0N> Produit\n\
Produit: référence [CHAR(4)], libellé, prixCatalogue [FLOAT]";
	} else if (example == "bibliotheque") {
		source = "Oeuvre: id [COUNTER], titre, resume [TEXT]\n\
EtreDisponible, _11 Exemplaire, 0N Oeuvre\n\
Exemplaire: no [INT], dateAchat [DATE]\n\
\n\
Revue: frequenceParution [INT]\n\
Livre: dateParution, isbn\n\
Concerner, 11 Emprunt, 0N Exemplaire\n\
\n\
Abonne: id [COUNTER], nom, prenom\n\
Effectuer, 11 Emprunt, 0N Abonne\n\
Emprunt: id [COUNTER], dateEmprunt [DATE], dateRetour [DATE]\n\
\n\
/X\\ Oeuvre - Revue, Livre";
	} else if (example == "filepile") {
		source = "File:\n\
Pile: -_elements [Array<T>]\n\
\n\
Element: +_valeur [T]\n\
Suivre, 01 Element, +01> [suivant] Element\n\
\n\
AvoirPourTete, 01 File, o-01> [tete] Element\n\
AvoirPourQueue, 01 File, o-01> [queue] Element\n\
\n\
File(): (), estVide() [Bool], taille() [Int], enfiler(o [T]), defiler() [T]\n\
Pile(): estVide() [Bool], taille() [Int], empiler(o [T]), depiler() [T]";
	}
	document.getElementById("source").value = source;
	setOptionValue("mfd1", mfd1);
	setOptionValue("mfd2", mfd2);
	doDisplay();
	on_page_change(1);
}


function loadFile(file) {
	let reader = new FileReader();
	reader.onloadend = function() {
		document.getElementById("source").value = reader.result;
		on_view_change(1);
		doDisplay();
	};
	reader.readAsText(file, "utf-8");
}


function on_body_load() {
	let params = new URLSearchParams(window.location.search);
	//~ if (params.has("source") && (params.has("view") || params.has("api"))) { //for embedding (DISABLED)
		//~ let diagram = source.Mocodo.load(params.get("source") + "\n");
		//~ if (diagram != null) {
			//~ let mld = transform.DiagramToMLD.transform(diagram);
			//~ transform.DiagramToUML.transform(diagram);
			//~ if (params.has("view")) {
				//~ document.body.innerHTML = generateContent(diagram, mld, params.get("view"));
				//~ document.body.style.textAlign = "center";
			//~ } else { //api
				//~ let content = generateContent(diagram, mld, params.get("api"));
				//~ let mimetype = content.substring(1, 4) == "svg" ? "image/xml+svg" : "text/html";
				//~ location.href = URL.createObjectURL(new Blob([content], { type: mimetype }));
			//~ }
			//~ return;
		//~ }
	//~ } else {
		let doc = window.location.search.substring(1);
		if (params.has("mfd1")) {
			setOptionValue("mfd1", params.get("mfd1"));
		}
		if (params.has("mfd2")) {
			setOptionValue("mfd2", params.get("mfd2"));
		}
		if (params.has("source")) {
			document.getElementById("source").value = params.get("source"); //doesn't fire on_source_change() event
		} else if (doc != "") { //legacy behavior
			document.getElementById("source").value = decodeURI(doc);
		}
		doDisplay();
	//~ }

	function updateOrientation() {
		setTimeout(function() {
			if (window.innerWidth < window.innerHeight) {
				document.getElementById("body").removeEventListener("touchstart", on_pointerdown);
				document.getElementById("body").removeEventListener("touchmove", on_pointermove);
				document.getElementById("body").removeEventListener("touchend", on_pointerup);
				document.getElementById("body").removeEventListener("wheel", on_wheel);
			} else {
				document.getElementById("body").addEventListener("touchstart", on_pointerdown);
				document.getElementById("body").addEventListener("touchmove", on_pointermove);
				document.getElementById("body").addEventListener("touchend", on_pointerup);
				document.getElementById("body").addEventListener("wheel", on_wheel);
			}
		}, 300); //give some milliseconds to update values
	}
	window.onorientationchange = updateOrientation;
	updateOrientation();

	if (document.getElementById("source").value != "") {
		on_view_change(1);
	}
	//~ document.getElementById("source").focus();
	
}


function on_copy(id) {
	function doCopy() {
		let zone = document.getElementById(id);
		let cbi = null;
		if (zone.nodeName.toUpperCase() == "TEXTAREA" || zone.firstChild.nodeName.toUpperCase() == "SVG") {
			cbi = new ClipboardItem({ ["text/plain"]: new Blob([getContent(id)], { type: "text/plain" }) })
		} else {
			cbi = new ClipboardItem({
				["text/plain"]: new Blob([getContent(id, true)], { type: "text/plain" }),
				["text/html"]: new Blob([getContent(id)], { type: "text/html" })
			});
		}
		navigator.clipboard.write([cbi]).then(function() {
			displayCheck(id + "Copy");
		}, function(err) { 
			console.log(err);
		});
	}

	navigator.permissions.query({name: "clipboard-write"}).then(result => {
			if (result.state == "granted" || result.state == "prompt") doCopy();
		}, err => { //Firefox doesn't support "clipboard-write" Permission (https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Interact_with_the_clipboard)
			doCopy(); //Firefox requires dom.events.asyncClipboard.clipboardItem preference set to true (https://developer.mozilla.org/en-US/docs/Web/API/ClipboardItem)
		}
	);
}


function on_download(id) {
	let filename = prompt("Nom du fichier :", "");
	if (filename != null && filename != "") {
		filename = getFilename(id, filename);
		if (document.getElementById(id).nodeName.toUpperCase() != "TEXTAREA" && document.getElementById(id).firstChild.nodeName.toUpperCase() == "DIV") {
			let foldername = filename.substring(0, filename.length - 4);
			download(filename, "data:application/zip;base64," + JsZip.zip(id, foldername));
		} else {
			download(filename, "data:" + getMimeType(id) + ";charset=utf-8," + encodeURIComponent(getContent(id, true)));
		}
	}
}


function on_drag_file(event) {
	event.stopPropagation();
	event.preventDefault();
	event.dataTransfer.dropEffect = "copy";
}


function on_drop_file(event) {
	event.stopPropagation();
	event.preventDefault();
	if (event.dataTransfer.files.length == 1) {
		loadFile(event.dataTransfer.files.item(0));
	}
}


function on_page_change(direction) {
	let newPageIndex = pageIndex + 1 * direction;
	if (newPageIndex > -1 && newPageIndex < PAGES.length - 1) {
		on_view_change(newPageIndex);
	}
}


function on_pointerdown(event) {
	touchStartX = event.changedTouches[0].pageX;
	touchStartY = event.changedTouches[0].pageY;
	touchStartTime = new Date().getTime();
	for (let i=0; i<PAGES.length; i++) {
		pagePos[i] = document.getElementById(PAGES[i]).getBoundingClientRect().left;
	}
}


function on_pointermove(event) {
	let target = event.target;
	while (target.getAttribute("class") != "pageContent" && target.parentNode != null) {
		target = target.parentNode;
	}
	let deltaX = touchStartX - event.changedTouches[0].pageX;
	let deltaY = touchStartY - event.changedTouches[0].pageY;
	if (target.clientWidth - target.scrollWidth == 1 && Math.abs(deltaX) > Math.abs(deltaY)) {
		for (i=0; i<PAGES.length; i++) {
			document.getElementById(PAGES[i]).style.left = (pagePos[i] - deltaX) + "px";
		}
	}
}


function on_pointerup(event) {
	let delta = touchStartX - event.changedTouches[0].pageX;
	let delay = new Date().getTime() - touchStartTime;
	let remainingTime = Math.round(delay / Math.abs(delta) * (window.innerWidth / 2 - Math.abs(delta)));
	if ((Math.abs(delta) > SWIPE_DIST) && (delay < SWIPE_DELAY)) {
		if (delta > 0 && pageIndex != PAGES.length - 2) {
			on_view_change(pageIndex + 1, remainingTime);
		} else if (delta < 0 && pageIndex != 0) {
			on_view_change(pageIndex - 1, remainingTime);
		} else {
			on_view_change(pageIndex, PAGE_TRANSITION / 2);
		}
		event.preventDefault();
	} else {
		on_view_change(pageIndex, PAGE_TRANSITION / 2);
	}
	touchStartX = -1;
}


function on_select_file(fileInput) {
	if (fileInput.files.length == 1) {
		loadFile(fileInput.files.item(0));
	}
}


function on_share(/*mfd*/) {
	let doc = encodeURI(document.getElementById("source").value);
	//~ if (mfd == null) {
		let params = "?mfd1=" + getOptionValue("mfd1") + "&mfd2=" + getOptionValue("mfd2") + "&source=" + doc;
		window.history.replaceState({}, document.title, params);
		navigator.clipboard.writeText(document.URL + params);
		let mfd = "source";
	//~ } else { //DISABLED
		//~ let url = document.URL + "?view=" + getOptionValue(mfd) + "&source=" + doc;
		//~ let zone = document.getElementById(mfd).firstChild;
		//~ let html='<iframe src="' + url + '" title="' + getOptionValue(mfd) + '" height="' + (zone.clientHeight + 10) + '" width="' + (zone.clientWidth + 10) + '"></iframe>';
		//~ navigator.clipboard.writeText(html);
	//~ }
	displayCheck(mfd + "Share");
}


function on_source_change() {
	if (window.location.search != "") { //resets search string
		let len = window.location.href.length - window.location.search.length;
		window.history.replaceState({}, document.title, window.location.href.substring(0, len));
	}
	doDisplay();
}


function on_fullscreen(id) {
	window.open(URL.createObjectURL(new Blob([document.getElementById(id).innerHTML], { type: getMimeType(id) + ";charset=utf-8" })));
}


function on_view_change(newPageIndex, duration = PAGE_TRANSITION) {
	for (let i=0; i<PAGES.length; i++) {
		let iPage = document.getElementById(PAGES[i]);
		iPage.style.transition = "left " + duration + "ms";
		iPage.style.left = (i - newPageIndex) * 50 + "%";
	}
	pageIndex = newPageIndex;
	setTimeout(function() {
		if (pageIndex == 0) {
			document.getElementById("prev1").style.visibility = "hidden";
			document.getElementById("next1").style.visibility = "visible";
		} else {
			document.getElementById("prev1").style.visibility = "visible";
			document.getElementById("next1").style.visibility = "hidden";
		}
		if (pageIndex == 1) {
			document.getElementById("prev2").style.visibility = "hidden";
			document.getElementById("next2").style.visibility = "visible";
		} else {
			document.getElementById("prev2").style.visibility = "visible";
			document.getElementById("next2").style.visibility = "hidden";
		}
	}, duration);
}


function on_wheel(event) {
	if (event.shiftKey) {
		if (event.deltaY > 0 && pageIndex != PAGES.length - 2) {
			on_view_change(pageIndex + 1);
		} else if (event.deltaY < 0 && pageIndex != 0) {
			on_view_change(pageIndex - 1);
		}
	}
}

function setOptionValue(group, value) {
	let items = document.getElementsByName(group);
	for (let i = 0; i < items.length; i++) {
		if (items[i].value == value) {
			items[i].checked = true;
		} else {
			items[i].checked = false;
		}
	}
}
