var ToolMan = {
	events : function() {
		if (!ToolMan._eventsFactory) throw "ToolMan Events module isn't loaded";
		return ToolMan._eventsFactory;
	},

	css : function() {
		if (!ToolMan._cssFactory) throw "ToolMan CSS module isn't loaded";
		return ToolMan._cssFactory;
	},

	coordinates : function() {
		if (!ToolMan._coordinatesFactory) throw "ToolMan Coordinates module isn't loaded";
		return ToolMan._coordinatesFactory;
	},

	drag : function() {
		if (!ToolMan._dragFactory) throw "ToolMan Drag module isn't loaded";
		return ToolMan._dragFactory;
	},

	dragsort : function() {
		if (!ToolMan._dragsortFactory) throw "ToolMan DragSort module isn't loaded";
		return ToolMan._dragsortFactory;
	},

	helpers : function() {
		return ToolMan._helpers;
	},

	cookies : function() {
		if (!ToolMan._cookieOven) throw "ToolMan Cookie module isn't loaded";
		return ToolMan._cookieOven;
	},

	junkdrawer : function() {
		return ToolMan._junkdrawer;
	}
};

ToolMan._helpers = {
	map : function(array, func) {
		for (var i = 0, n = array.length; i < n; i++) func(array[i]);
	},

	nextItem : function(item, nodeName) {
		if (item == null) return;
		var next = item.nextSibling;
		while (next != null) {
			if (next.nodeName == nodeName) return next;
			next = next.nextSibling;
		}
		return null;
	},

	previousItem : function(item, nodeName) {
		var previous = item.previousSibling;
		while (previous != null) {
			if (previous.nodeName == nodeName) return previous;
			previous = previous.previousSibling;
		}
		return null;
	},

	moveBefore : function(item1, item2) {
		var parent = item1.parentNode;
		parent.removeChild(item1);
		parent.insertBefore(item1, item2);
	},

	moveAfter : function(item1, item2) {
		var parent = item1.parentNode;
		parent.removeChild(item1);
		parent.insertBefore(item1, item2 ? item2.nextSibling : null);
	}
};

/** 
 * scripts without a proper home
 *
 * stuff here is subject to change unapologetically and without warning
 */
ToolMan._junkdrawer = {
	serializeList : function(list) {
		var items = list.getElementsByTagName("li");
		var array = new Array();
		for (var i = 0, n = items.length; i < n; i++) {
			var item = items[i];
			array.push(ToolMan.junkdrawer()._identifier(item));
		}
		return array.join('|');
	},

	inspectListOrder : function(id) {
		//alert(ToolMan.junkdrawer().serializeList(document.getElementById(id)))
	},

	restoreListOrder : function(listID) {
		var list = document.getElementById(listID);
		if (list == null) return;

		var cookie = ToolMan.cookies().get("list-" + listID);
		if (!cookie) return;

		var IDs = cookie.split('|');
		var items = ToolMan.junkdrawer()._itemsByID(list);

		for (var i = 0, n = IDs.length; i < n; i++) {
			var itemID = IDs[i];
			if (itemID in items) {
				var item = items[itemID];
				list.removeChild(item);
				list.insertBefore(item, null);
			}
		}
	},

	_identifier : function(item) {
		var trim = ToolMan.junkdrawer().trim();
		var identifier;
		identifier = trim(item.getAttribute("id"));
		if (identifier != null && identifier.length > 0) return identifier;
		
		identifier = trim(item.getAttribute("itemID"));
		if (identifier != null && identifier.length > 0) return identifier;
		
		// FIXME: strip out special chars or make this an MD5 hash or something
		return trim(item.innerHTML);
	},

	_itemsByID : function(list) {
		var array = new Array();
		var items = list.getElementsByTagName('li');
		for (var i = 0, n = items.length; i < n; i++) {
			var item = items[i];
			array[ToolMan.junkdrawer()._identifier(item)] = item;
		}
		return array;
	},

	trim : function(text) {
		if (text == null) return null;
		return text.replace("/^(\s+)?(.*\S)(\s+)?$/", '$2');
	}
}
