/* Copyright (c) 2005 Tim Taylor Consulting (see LICENSE.txt) */

ToolMan._dragsortFactory = 
{
	makeSortable : function(item) 
	{
		var group = ToolMan.drag().createSimpleGroup(item);		
		group.register('dragstart', this._onDragStart);
		group.register('dragmove', this._onDragMove);
		group.register('dragend', this._onDragEnd);
		return group;			
	},
	
	/** 
	 * Iterates over a list's items, making them sortable, applying
	 * optional functions to each item.
	 *
	 * example: makeListSortable(myList, myFunc1, myFunc2, ... , myFuncN)
	 */
	makeListSortable : function(list, constrainCallBackFunction, onDragStopEventCallBack) 
	{
		var helpers = ToolMan.helpers();
		var coordinates = ToolMan.coordinates();
		var items = this._getListItems(list, onDragStopEventCallBack);		
		helpers.map(items, function(item) 
		{
			var dragGroup = ToolMan._dragsortFactory.makeSortable(item);
			dragGroup.setThreshold(4);
			var min;
			var max;
			dragGroup.addTransform(function(coordinate, dragEvent) {
				return coordinate.constrainTo(min, max);
			})
			dragGroup.register('dragstart', function() {
				var items = list.getElementsByTagName("li");
				min = max = coordinates.topLeftOffset(items[0]);
				for (var i = 1, n = items.length; i < n; i++) 
				{
					var offset = coordinates.topLeftOffset(items[i]);
					min = min.min(offset);
					max = max.max(offset);
				}
			})
		})
		
		// Map constrain function
		helpers.map(items, arguments[1]);
	},
	
	_getListItems: function(list, onDragStopEventCallBack)
	{
		var listItems = new Array();
		var items = list.getElementsByTagName("li");
		
		for(var nCnt=0; nCnt<items.length; nCnt++)
		{
			if(items[nCnt])
			{
				if(items[nCnt].getAttribute("isDraggable"))
				{	
					if(items[nCnt].getAttribute("isDraggable") == "1")
					{
						items[nCnt].onDragStopEventCallBack = onDragStopEventCallBack;
						listItems.push(items[nCnt]);
					}
				}				
			}
		}		
		nCnt = null;		
		return listItems;		
	},

	_onDragStart : function(dragEvent) {		
	},

	_onDragMove : function(dragEvent) {		
		var helpers = ToolMan.helpers();
		var coordinates = ToolMan.coordinates();

		var item = dragEvent.group.element;
		var xmouse = dragEvent.transformedMouseOffset;
		var moveTo = null;

		var previous = helpers.previousItem(item, item.nodeName);
		while (previous != null) {
			var bottomRight = coordinates.bottomRightOffset(previous);
			if (xmouse.y <= bottomRight.y && xmouse.x <= bottomRight.x) {
				moveTo = previous;
			}
			previous = helpers.previousItem(previous, item.nodeName);
		}
		if (moveTo != null) {
			helpers.moveBefore(item, moveTo);
			return;
		}

		var next = helpers.nextItem(item, item.nodeName);
		while (next != null) {
			var topLeft = coordinates.topLeftOffset(next);
			if (topLeft.y <= xmouse.y && topLeft.x <= xmouse.x) {
				moveTo = next;
			}
			next = helpers.nextItem(next, item.nodeName);
		}
		if (moveTo != null) {
			helpers.moveBefore(item, helpers.nextItem(moveTo, item.nodeName));
			return;
		}
	},

	_onDragEnd : function(dragEvent) 
	{
		ToolMan.coordinates().create(0, 0).reposition(dragEvent.group.element);
		if(dragEvent.group.element.onDragStopEventCallBack)
		{
			dragEvent.group.element.onDragStopEventCallBack();
		}
	}
};