// <nowiki>
// Forked from ] by ]
// Forked by ]. For full list of changes see ]
// Version 2.3.2

// Retrieve and Set Global variables
if (gTidyCiteEditSum == null) var gTidyCiteEditSum = true; //generate a short summary
if (gTidyCiteShowDiff == null) var gTidyCiteShowDiff = true; //show diff after
if (gTidyCiteMarkMinor == null) var gTidyCiteMarkMinor = true; //mark edit as minor
if (gTidyCiteReplaceParams == null) var gTidyCiteReplaceParams = true; //replace deprecated parameters
if (gTidyCiteRemoveLive == null) var gTidyCiteRemoveLive = true; //remove url-status=live on unarchived refs
if (gTidyCiteReplacementParams == null) var gTidyCiteReplacementParams = {}; //initialise empty object if no user values found

mw.loader.using("mediawiki.util", function () {
	// Only run script if user is editing an article
	if (!document.forms.editform || (mw.config.get("wgAction") !== "edit" && mw.config.get("wgAction") !== "submit")) {
		return;
	}

	// Deprecated parameters to replace
	var deprecatedParams = { //gTidyCiteReplacementParams
		"accessdate": "access-date",
		"archiveurl": "archive-url",
		"archivedate": "archive-date",
		"urlstatus": "url-status",
		"urlaccess": "url-access",
		"transcripturl": "transcript-url",
		"authorlink": "author-link"
	};
	// If custom user list exists, append to and supersede the default param replace list
	deprecatedParams = Object.assign(deprecatedParams, gTidyCiteReplacementParams);

	function TidyCitations(mode) {
		// WikEd compatibility
		const useWikEd = window.wikEd && window.wikEd.useWikEd;
		if (useWikEd) {
			window.wikEd.UpdateTextarea();
		}

		// Get and check textbox and summary field
		var textbox = $("#wpTextbox1");
		var summary = $("#wpSummary");
		if (!textbox) {
			mw.notify("Textbox not found | Tidy Citations");
			return false;
		}
		if (!summary) {
			mw.notify("Summary box not found | Tidy Citations");
			return false;
		}
		var txt = textbox.val();
		const original = txt;
		var hyphenToggle = false;
		var statusToggle = false;

		const paramRegex = / *\| *(+) *= */g;
		var customRegex;
		if (mode === "custom") {
			customRegex = prompt("Please enter your custom format, using the following examples: ' |$1=' or '|$1=' or ' | $1 = '");
			console.log(customRegex);
			if ((customRegex.match(/?(\s*\|\s*\$1\s*=\s*)?/g) || ).length !== 1) {
				mw.notify("Invalid custom format entered | Tidy Citations");
				return false;
			}
			customRegex = customRegex.replace(//g, "");
		}

		// Fill an array with one entry per each recognized citation template
		var oldTemplates = txt.match(/{{*it(?:ation|e*)*\|(?:{{*}}|)+}}/g) || ;
		var newTemplates = oldTemplates.slice();
		//var archiveTemplates = txt.match(/{{*eb(?:\.|*)archive*\|(?:{{*}}|)+}}/g) || ; //TODO : Tie in
		//var allReferences = txt.match(/<ref(?:\s+name\s*=.+?)?\s*>.*?<\/ref\s*>|<ref\s+name\s*=.+?\/>/gsi); // Get full text within ref tags
		// /{{*ondon*azette*\|	(London Gazette)

		for (var i = 0; i < oldTemplates.length; i++) {

			// Replace deprecated non-hyphenated parameters
			if (gTidyCiteReplaceParams) {
				for (let key in deprecatedParams) {
					if (deprecatedParams.hasOwnProperty(key)) {
						let deprecatedRegex = new RegExp("\\| *" + key + " *=", "gi");
						if (deprecatedRegex.test(newTemplates)) {
							newTemplates = newTemplates.replace(deprecatedRegex, "|" + deprecatedParams + "=");
							hyphenToggle = true;
						}
					}
				}
			}

			//Remove "|url-status=live" if there is no archive link
			if (gTidyCiteRemoveLive && /\|\s*url-?status\s*=\s*live/.test(newTemplates)) { //Fix .test
				if (!(/\|\s*archive-?url\s*=\s*http/.test(newTemplates))) {
					newTemplates = newTemplates.replace(/\|\s*url-?status\s*=\s*live/,"");
					statusToggle = true;
				}
			}

			// standard, crammed, roomy & custom
			if (mode !== "vertical") {
				// Remove newlines
				newTemplates = newTemplates.replace(/\n/g, "");
				
				switch (mode) { // Normalize spaces around the pipes and equal signs
					case "standard":
						newTemplates = newTemplates.replace(paramRegex, " |$1=");
						break;
					case "crammed":
						newTemplates = newTemplates.replace(paramRegex, "|$1=");
						break;
					case "roomy":
						newTemplates = newTemplates.replace(paramRegex, " | $1 = ");
						break;
					case "custom":
						newTemplates = newTemplates.replace(paramRegex, customRegex);
						break;
				}
				// Remove potential extra spaces before template ends
				newTemplates = newTemplates.replace(/\s*}}$/, "}}");
				txt = txt.replace(oldTemplates, newTemplates);
				// vertical
			} else {
				// Fill an array with one entry per each parameter for this citation template
				var oldParams = oldTemplates.match(/ *\n? *\| *\n? *(+) *= */g);
				var newParams = ;
				var maxWidth = 0;
				for (var j = 0; j < oldParams.length; j++) {
					// Get rid of the delimiters and spaces, keep only the parameter string
					newParams = oldParams.match(/+/);
					// Calculate the length of the longest parameter
					maxWidth = (newParams.length > maxWidth) ? newParams.length : maxWidth;
				}
				maxWidth++; // We need an extra one because Array(n).join(' ') will produce a string with n-1 chars

				// Generate the aligned versions of the parameters (with padding before the equal signs)
				for (var k = 0; k < oldParams.length; k++) {
					var numSpaces = maxWidth - newParams.length;
					var alignedParam = "\n  | " + newParams + new Array(numSpaces).join(" ") + " = ";
					// Replace the original parameters with the tweakes ones
					newTemplates = newTemplates.replace(oldParams, alignedParam);
				}

				// Also align the }}
				newTemplates = newTemplates.replace(/ *\n? *}}/g, "\n}}");
				// Replace the original templates with the tweaked versions
				txt = txt.replace(oldTemplates, newTemplates);
			}
		}
		// Only insert the text if something has changed
		if (txt !== original) {
			textbox.val(txt); //update text
			if (useWikEd) wikEd.UpdateFrame(); //wikEd compatibility
			if (gTidyCiteEditSum) summary.val(EditSummary(summary.val(), hyphenToggle, statusToggle)); //edit summary
			if (gTidyCiteMarkMinor) document.editform.wpMinoredit.checked = true; //mark as minor
			if (gTidyCiteShowDiff) $("#wpDiff").click(); //show changes
		} else {
			mw.notify("No changes made | Tidy Citations");
		}
	}

	// Generate a random alphanumeric ID of set length
	function GetUniqueID(length) {
		const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
		var result = "";
		for (let i = 0; i < length; i++) {
			result += chars;
		}
		return result;
	}

	// Substitute comments with placeholders
	function RemoveComments(citeTemplate) {
		const commentText = ;
		const commentMatches = citeTemplate.match(/<!--.*?-->/gs); //Get all comments
		for (let i = 0; i < commentMatches.length; i++) {
			var subText = GetUniqueID(10);
			while (citeTemplate.indexOf(subText) !== -1) {
				subText = GetUniqueID(10);
			}
			commentText.push(]);
			citeTemplate = citeTemplate.replace(commentMatches, subText);
		}
		return { commentText, citeTemplate };
	}
	// a = RemoveComments("Test")
	// b = a.commentText
	// c = a.newTemplates

	// Restore comments from placeholders
	function RestoreComments(citeTemplate, commentText) {
		for (let key in commentText) {
			if (commentText.hasOwnProperty(key)) {
				citeTemplate = citeTemplate.replace(key, commentText);
			}
		}
		return citeTemplate;
	}

	// Get array of parameters split by "|" and then split by "="
	function SplitParams(citeTemplate) {
		var paramList = citeTemplate
			.split("|")
			.map(element => element.split(/=(.*)/s)
				.map(element => element.trim())
				.filter(element => element !== ""));
		return paramList;
	}

	// Append custom message unto the end of the current edit dummary
	function EditSummary(sum, hyphenToggle, statusToggle) {
		// Define edit summary messages
		const spaceSum = "Standardise citation spacing";
		const hyphenSum = " replace deprecated fields";
		const statusSum = " remove 'url-status=live' from non-archived refs";
		const linkSum = " using ]";
		
		var repeatSummary = sum.indexOf(linkSum) !== -1;
		var currentRegex;
		if (repeatSummary) {
			// Merge toggles from previous edit summary
			currentRegex = new RegExp(spaceSum + ".*?" + linkSum.replace(/(\/\|])/g, "\\$1"), "gs");
			var currentSum = sum.match(currentRegex) || ;
			hyphenToggle = hyphenToggle || currentSum.indexOf(hyphenSum) !== -1;
			statusToggle = statusToggle || currentSum.indexOf(statusSum) !== -1;
		}
		
		// Build edit summary
		var firstAppend = true;
		var appendSum = linkSum;
		if (statusToggle === true) {
			appendSum = " and" + statusSum + appendSum;
			firstAppend = false;
		}
		if (hyphenToggle === true) {
			appendSum = (firstAppend ? " and" : ",") + hyphenSum + appendSum;
			firstAppend = false;
		}
		appendSum = spaceSum + appendSum;
		
		// Merge script summary and existing summary
		if (repeatSummary) {
			// Script re-run
			sum = sum.replace(currentRegex, appendSum);
		} else {
			// First time
			if (/?\s*$/.test(sum)) {
				sum += " | " + appendSum;
			} else {
				sum = appendSum;
			}
		}
		return sum;
	}

	var tidyButton1 = mw.util.addPortletLink("p-tb", "#", "{{Tidy}}", "t-tidyCiteDefault", "Format citations: tidy whitespace");
	var tidyButton2 = mw.util.addPortletLink("p-tb", "#", "{{Tidy}} (Vertical)", "t-tidyCiteVertical", "Formats citations & tidy whitespace (vertically)");
	var tidyButton3 = mw.util.addPortletLink("p-tb", "#", "{{Crammed}}", "t-tidyCiteCrammed", "Formats citations without any whitespace whatsoever");
	var tidyButton4 = mw.util.addPortletLink("p-tb", "#", "{{Roomy}}", "t-tidyCiteRoomy", "Formats citations with a lot of whitespace");
	var tidyButton5 = mw.util.addPortletLink("p-tb", "#", "{{Custom}}", "t-tidyCiteCustom", "Formats citations with custom format");
	$(tidyButton1).click(function () { TidyCitations("standard"); });
	$(tidyButton2).click(function () { TidyCitations("vertical"); });
	$(tidyButton3).click(function () { TidyCitations("crammed"); });
	$(tidyButton4).click(function () { TidyCitations("roomy"); });
	$(tidyButton5).click(function () { TidyCitations("custom"); });

});
// </nowiki>