// http://akelpad.sourceforge.net/forum/viewtopic.php?p=27896#27896
// Description(1033): Works with HTML Tidy: validate / formatting
// Description(1049): Работа с HTML Tidy: валидация / форматирование
// Version: 1.3 (2015.04.10)
// Author: VladSh
// Initial code: Instructor
// 
// Dependencies:
// 	...\Include\ShowMenuEx.js
// 
// Default tooldir and configdir is ...\AkelPad\AkelFiles\Tools\HTMLTidy\.
// If your tooldir and/or configdir differ from those of the default, then set them in tidy.ini.
// 
// Arguments:
// 	action: [0] - validate, 1 - formatting
// 	xml: [0] or without this argument - html, 1 - xml
// 	config - config filename's, -config="?" will show the list for a config choise (from param-file)
// 		if the config setted as filename only then the config-files must be placed in tooldir;
// 		if the config has been set, the options below will be ignored
// 	spaces - number of spaces in Tab; by default takes from program settings
// 
// Usage:
// Если в tidy.ini параметр pExt=ini:
// 	-"Tidy валидация XML" Call("Scripts::Main", 1, "tidy.js", `-xml=1`)
// 	-"Tidy валидация HTML" Call("Scripts::Main", 1, "tidy.js")
// 	-"Tidy форматирование XML" Call("Scripts::Main", 1, "tidy.js", `-xml=1 -action=1`)
// 	-"Tidy форматирование HTML" Call("Scripts::Main", 1, "tidy.js", `-action=1`)
// 	-"Tidy форматирование с выбором конфига" Call("Scripts::Main", 1, "tidy.js", `-action=1 -config="?"`)
// Если в tidy.ini параметр pExt=json (в json-файле можно задать все аргументы каждой строки меню):
// 	"Tidy валидация XML" Call("Scripts::Main", 1, "tidy.js", `-pID="vXML"`) - задействование определённого шаблона настроек из json-файла по ID

if (! AkelPad.Include("ShowMenuEx.js")) WScript.Quit();
var fLogOutput = "Log::Output";
var repattern = "^line (\\d+) column (\\d+)";
var retags = "/GOTOLINE=\\1:\\2";

initIniOptions(['tooldir', 'configdir', 'configlist', 'config', 'spaces']);

var tooldir = expandPath(opts['tooldir'] || (AkelPad.GetAkelDir() + '\\AkelFiles\\Tools\\HTMLTidy\\'));
var toolpath = tooldir + 'tidy.exe';
checkFilePath("Tidy", toolpath);

var cmdline = toolpath + ' --input-xml ' + AkelPad.GetArgValue("xml", 0 /* html */) + ' --quiet 1 -errors';
AkelPad.Call(fLogOutput, 1, cmdline, "", repattern, retags, 65001, 65001, 4160 /*64+4096*/);
while (getExecState())
	WScript.Sleep(100);

if (getExitCode() == 0) {
	AkelPad.Call(fLogOutput, 6);
	if (AkelPad.GetArgValue("action", 0) == 0) {
		AkelPad.MessageBox(hWndMain, "Document is valid.", WScript.ScriptName, 64 /*MB_ICONINFORMATION*/);
	}
	else {
		switch (opts['pExt']) {
			case "json":
				if (!initMenuParams(POS_CURSOR)) WScript.Quit();
				break;
			case "ini":
				initArgs(['config', 'spaces']);
				break;
			default:
				AkelPad.Call(fLogOutput, 4, WScript.ScriptName + ": pExt='" + opts['pExt'] + "' is not supported.");
				WScript.Quit();
		}
		config = opts['config'];
		if (config) {
			if (config == "?") {
				if (opts['configlist']) {
					opts['pExt'] = "";
					opts['pFile'] = opts['configlist'];
				}
				config = getSelectedMenuItem(POS_CURSOR, false);
				if (!config) WScript.Quit();
			}
			if (config.indexOf('\\') == -1) {
				config = (opts['configdir'] || tooldir) + config;
			}
			config = expandPath(config);
			checkFilePath("Config", config);
			
			cmdline = toolpath + ' -config "' + config + '"';
		}
		else {
			var nTabStop = opts['spaces'] || AkelPad.SendMessage(AkelPad.GetEditWnd(), 3239 /*AEM_GETTABSTOP*/, 0, 0);
			
			cmdline = toolpath + ' --indent auto --indent-spaces ' + nTabStop + ' --wrap 0 --quiet 1';
		}
		
		AkelPad.Call(fLogOutput, 1, cmdline, "", repattern, retags, 65001, 65001, 1052673);
	}
}
else
	AkelPad.SendMessage(hWndMain, 1278 /*AKD_DOCK*/, 0x200 /*DK_SHOW*/, getOutputDock());


function getExecState() {
	var lpState;
	var nState = 0;
	if (lpState = AkelPad.MemAlloc(4 /*sizeof(DWORD)*/)) {
		AkelPad.Call(fLogOutput, 3, lpState);
		nState = AkelPad.MemRead(lpState, 3 /*DT_DWORD*/);
		AkelPad.MemFree(lpState);
	}
	return nState;
}

function getExitCode() {
	var lpCode;
	var nCode = 0;
	if (lpCode = AkelPad.MemAlloc(4 /*sizeof(DWORD)*/)) {
		AkelPad.Call(fLogOutput, 3, 0, 0, 0, 0, lpCode);
		nCode = AkelPad.MemRead(lpCode, 3 /*DT_DWORD*/);
		AkelPad.MemFree(lpCode);
	}
	return nCode;
}

function getOutputDock() {
	var lpDock;
	var hDock = 0;
	if (lpDock = AkelPad.MemAlloc(_X64?8:4 /*sizeof(DOCK *)*/)) {
		AkelPad.Call(fLogOutput, 2, 0, lpDock);
		hDock = AkelPad.MemRead(lpDock, 2 /*DT_QWORD*/);
		AkelPad.MemFree(lpDock);
	}
	return hDock;
}