/** Function to ajaxify forms with "nation", "region", "city" and "suburb" selectors.
 *
 * \param form DOM element of form to ajaxify
 * \param ajaxurlfmt URL format string to get XML list of locations from.
 * \param anytext Text to use for "--Any--" options.
 *
 * The \p ajaxurlfmt parameter should have "{0-3}" elements in it which will be
 * replaced by the ids to get locations for.
 */
function
location_dropdown_dynamicise(form, ajaxurlfmt, anytext)
{
	var nations = null;
	var regions = null;
	var cities = null;
	var suburbs = null;

	if (!form
			|| !form.tagName
			|| form.tagName.toLowerCase() != 'form')
	{
		return;
	}


	/** Add an <option> node to a <select> element. */
	function addSelectOption(element, value, text)
	{
		var child = element.ownerDocument.createElement('option');
		child.setAttribute('value', value);
		child.appendChild(element.ownerDocument.createTextNode(text));
		element.appendChild(child);
	}


	/** Set the options of a location drop-down from XML elements */
	function setlocationelem(element, datanodes)
	{
		if (!element || !datanodes) {
			return;
		}

		if (octalClass_inlist(element, 'static')) {
			return;
		}

		var values = octalFormElementValues(element);

		octalRemoveAllChildren(element);
		addSelectOption(element, '', anytext);
		for (var i = 0; i < datanodes.length; ++i) {
			var datanode = datanodes.item(i);
			addSelectOption(element,
					datanode.getAttribute('name'),
					octalDomText(datanode));
		}

		octalFormElementValuesSet(element, values);
	}


	/* TODO: return value probably should be URL encoded. Although
	 * values for these elements should be alnum-only
	 */
	function getfirstvalue(elem, levelok)
	{
		if (!elem) {
			return '';
		}
		if (!octalClass_inlist(elem, 'static')
				&& !levelok)
		{
			return '';
		}
		var values = octalFormElementValues(elem);
		if (!values || !values.length) {
			return '';
		}
		return values[0];
	}


	function
		enableElements(enabled)
		{
			if (nations) {
				nations.disabled = !enabled;
			}
			if (regions) {
				regions.disabled = !enabled;
			}
			if (cities) {
				cities.disabled = !enabled;
			}
			if (suburbs) {
				suburbs.disabled = !enabled;
			}
		}


	/** Get XML of locations from certain select elements
	 *
	 * TODO: Fix for the case where multiple elements are selected?
	 */
	function getlocations(levelload, levelset)
	{
		//var start = Date.now();
		/** Set the options of location drop-downs from XML locations */
		function setlocations(request)
		{
			if (request.readyState != 4) {
				return;
			}
			if (request.status != 200
					|| !request.responseXML)
			{
				alert(request.status + ': ' + request.responseText);
				enableElements(true);
				return;
			}

			//var t0 = Date.now();

			var locxml = request.responseXML;
			if (levelset < 1) {
				setlocationelem(nations,
						locxml.getElementsByTagName('nation'));
			}
			//var t1 = Date.now();
			if (levelset < 2) {
				setlocationelem(regions,
						locxml.getElementsByTagName('region'));
			}
			//var t2 = Date.now();
			if (levelset < 3) {
				setlocationelem(cities,
						locxml.getElementsByTagName('city'));
			}
			//var t3 = Date.now();
			if (levelset < 4) {
				setlocationelem(suburbs,
						locxml.getElementsByTagName('suburb'));
			}
			//var t4 = Date.now();
			enableElements(true);

			/*
			if (octalDebug) {
				alert(t0 - start
					+ ',\n' + (t1 - t0)
					+ ',\n' + (t2 - t1)
					+ ',\n' + (t3 - t2)
					+ ',\n' + (t4 - t3));
			}
			*/

			return;
		}

		enableElements(false);
		var url = octalFormat(ajaxurlfmt,
				getfirstvalue(nations, levelload >= 1),
				getfirstvalue(regions, levelload >= 2),
				getfirstvalue(cities, levelload >= 3),
				getfirstvalue(suburbs, levelload >= 4));
		if (octalDebug) {
			alert(url);
		}
		octalXmlHttpASync(url, setlocations);
	}


	for (var i = 0; i < form.elements.length; ++i) {
		var element = form.elements[i];

		if (element.tagName.toLowerCase() == 'select'
				&& element.type == 'select-one'
				&& element.name == 'nation')
		{
			nations = element;
			octalAddEventListener(nations, "change", function() {
					getlocations(1, 1);
					});
		}
		if (element.tagName.toLowerCase() == 'select'
				&& element.type == 'select-one'
				&& element.name == 'region')
		{
			regions = element;
			octalAddEventListener(regions, "change", function() {
					getlocations(2, 2);
					});
		}
		if (element.tagName.toLowerCase() == 'select'
				&& element.type == 'select-one'
				&& element.name == 'city')
		{
			cities = element;
			octalAddEventListener(cities, "change", function() {
					getlocations(3, 3);
					});
		}
		if (element.tagName.toLowerCase() == 'select'
				&& element.type == 'select-one'
				&& element.name == 'suburb')
		{
			suburbs = element;
			octalAddEventListener(suburbs, "change", function() {
					getlocations(4, 4);
					});
		}
	}

	if (!nations && !regions && !cities && !suburbs) {
		/* Does not have any selectors */
		return;
	}

	getlocations(4, 1);
}
