/**
 * VersionHandler handles versions. In other words, it gets
 * version information, manages the other versions dialog and
 * provides utility functions for finding and opening versions.
 */
function VersionHandler(animateDialogs, versionCancelButtonText, versionOKButtonText, noVersionsMessageText) {
	this.animateDialogs = animateDialogs;
	this.cancelButtonText = versionCancelButtonText;
	this.okButtonText = versionOKButtonText;
	this.verRequest = false;
	this.lastVerRequestData = false;
	this.postFunction = false;
	this.myVersions = false;
	this.noVersionsMessage = noVersionsMessageText;
}

/** Let the user choose a version via the other versions dialog. */
VersionHandler.prototype.chooseVersion = function() {
	if (this.myVersions) {
		this.showVersionDialog();
	} else {
		this.readVersions(this.showVersionDialog);
	}
}

/**
 * Read versions information and call the given function. Set the
 * function (fkn) as postFunction and get the versions.properties
 * from the server. Continue with buildVersionDialog.
 */ 
VersionHandler.prototype.readVersions = function(fkn) {
	this.postFunction = fkn;
	if (!this.myVersions) {
		this.verRequest = createXMLHttpRequest();
		this.verRequest.open('GET', 'versions.properties', false);
		this.verRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
		this.verRequest.send(null); // Blocking
		this.buildVersionDialog();
	} else {
		if (this.postFunction) this.postFunction();
	}
}

/**
 * Read the versions.properties data, save the version chain that the
 * current version belongs to and construct the other versions dialog.
 * Call the postFunction.
 */
VersionHandler.prototype.buildVersionDialog = function() {
	if (this.verRequest.readyState == 4) {
		if (this.verRequest.status == 200) {
			var allVersions = eval('(' + this.verRequest.responseText + ')');
			var currentRoot = allVersions.currentRoot;
			document.getElementById('tce_build').innerHTML = allVersions.currentRoot;
			for (var i=0; i<allVersions.versions.length; i++) {
				for (var j=0; j<allVersions.versions[i].length; j++) {
					if (this.matches(allVersions.versions[i][j], currentForm, currentRoot)) {
						this.myVersions = allVersions.versions[i];
						var prodName = document.getElementById('product_name').innerHTML;
						var verIndex = prodName.indexOf(allVersions.versions[i][j].ver);
						if (verIndex == -1 || verIndex < prodName.length - allVersions.versions[i][j].ver.length - 2) {
							document.getElementById('product_name').innerHTML += ' ' + allVersions.versions[i][j].ver;
							document.getElementById('product_name').versionString = allVersions.versions[i][j].ver;
						}
						break;
					}
				}
				if (this.myVersions) break;
			}
			document.getElementById('versionSelect').style.visibility='hidden';
			document.getElementById('version_link').style.visibility='hidden';
			if (this.myVersions) { 
				if (this.myVersions.length > 1) {
					var sel = document.getElementById('versionSelect');
					while (sel.length > 0) sel.remove(0); // empty
					for (var i=0; i<this.myVersions.length; i++) {
						var op = document.createElement('option');
						op.text = this.myVersions[i].ver + ' (' + this.myVersions[i].form + ')';
						if (this.matches(this.myVersions[i], currentForm, currentRoot)) {
							op.selected = true;
							op.value = '';
						} else {
							op.value = this.myVersions[i].url;
						}
						try {
							sel.add(op, null);
						} catch (err) { sel.add(op); } // IE
					}
					document.getElementById('version_link').style.visibility='visible';
				}
			}
			if (this.postFunction) this.postFunction();
		}
	}
}

/** Open the other versions dialog */
VersionHandler.prototype.showVersionDialog = function() {
	if (!this.myVersions) {
		Ext.MessageBox.alert(Ext.get('product_name').dom.innerHTML, this.noVersionsMessage);
		return;
	}
	if (!this.versionDlg) {
		this.versionDlg = new Ext.BasicDialog("version-dlg", {
			animateTarget: (this.animateDialogs ? 'version_link' : null),
			autoCreate: true,
			buttonAlign: 'left',
			collapsible: false,
			height:180,
			modal:true,
			resizable:false,
			shadow:true,
			width:400
		});
		this.versionDlg.addKeyListener(27, this.versionDlg.hide, this.versionDlg);
		this.versionDlg.addButton(this.okButtonText, this.doChooseVersion, this.versionDlg);
		this.versionDlg.addButton(this.cancelButtonText, this.versionDlg.hide, this.versionDlg);
		document.getElementById('versionSelect').style.visibility='visible';
	}
	this.versionDlg.show();
}

/**
 * Called if OK is pressed in the other versions dialog.
 * If another version has been selected, open it.
 * Else, just close the dialog.
 */
VersionHandler.prototype.doChooseVersion = function() {
	var sel = document.getElementById('versionSelect');
	if (sel.value && sel.value != '') {
		document.location = sel.value;
	} else {
		if (this.versionDlg) this.versionDlg.hide();
	}
}

/**
 * Check if a given version (toForm, toRoot) is the same version as
 * the current version (currentForm, fromRoot).
 */
VersionHandler.prototype.isSameVersion = function(toForm, toRoot, fromRoot) {
	if (toForm == currentForm && toRoot == fromRoot) return true;
	if (this.myVersions) {
		for (var i=0; i<this.myVersions.length; i++) {
			if (this.matches(this.myVersions[i], toForm, toRoot)
			 && this.matches(this.myVersions[i], currentForm, fromRoot)) {
				return true;
			}
		}
	}
	return false;
}

/**
 * Check if a given form (with a given root version) is a version
 * in the current version chain.
 */ 
VersionHandler.prototype.isFormAVersion = function(form, root) {
	if (this.myVersions) {
		for (var i=0; i<this.myVersions.length; i++) {
			if (this.matches(this.myVersions[i], form, root)) {
				return true;
			}
		}
	}
	return false;
}

/**
 * Open another version with saved data. This is done by putting the
 * data in a textarea and submitting the form to the other version's URL.
 * Generally, both form id and data is passed. In these cases, the form
 * if is passed as a "get parameter" and the data as a "post parameter".
 */
VersionHandler.prototype.openVersion = function(form, root, savedData) {
	if (this.myVersions) {
		for (var i=0; i<this.myVersions.length; i++) {
			if (this.matches(this.myVersions[i], form, root)) {
				document.getElementById('openother_form').action = this.myVersions[i].url;
				document.getElementById('openother_data').value = savedData;
				document.getElementById('openother_form').submit();
			}
		}
	}
	return false;
}

// Helpers

/** Does the array arr contain the value val? */
VersionHandler.prototype.contains = function(arr, val) {
	for (var i=0; i<arr.length; i++) {
		if (arr[i] == val) return true;
	}
	return false;
}

/**
 * Does the version (version.form, version.root) match the version
 * (form, root)? If version.root is undefined, the match depends
 * solely on the form.
 */
VersionHandler.prototype.matches = function(version, form, root) {
	return (
		(
			version.form.constructor == String &&
			version.form == form
		) || (
			version.form.constructor == Array &&
			this.contains(version.form, form)
		)
	) && (
		(
			!version.root
		) || (
			version.root.constructor == String &&
			version.root == root
		) || (
			version.root.constructor == Array &&
			this.contains(version.root, root)
		)
	);
}

