/**********************************************************
 Adapted from the sortable lists example by Tim Taylor
 http://tool-man.org/examples/sorting.html
 Modified by Tom Westcott : http://www.cyberdummy.co.uk 
 Modified by Liferay: http://www.liferay.com
 **********************************************************/

var DragDrop = {
	firstContainer : null,
	lastContainer : null,
    parent_id : null,
    parent_group : null,
	portletClassName: "portlet-boundary",

	makeListContainer : function(list, group) {
		// each container becomes a linked list node
		if (this.firstContainer == null) {
			this.firstContainer = this.lastContainer = list;
			list.previousContainer = null;
			list.nextContainer = null;
		} else {
			list.previousContainer = this.lastContainer;
			list.nextContainer = null;
			this.lastContainer.nextContainer = list;
			this.lastContainer = list;
		}
		
		// these functions are called when an item is draged over
		// a container or out of a container bounds.  onDragOut
		// is also called when the drag ends with an item having
		// been added to the container
        list.group = group;
		list.defaultClassName = "layout-column-default";
		list.highlightClassName = "layout-column-highlight";

    	var items = list.childNodes;
    	var items2;
		var curItem = null;
		var foundHandle = false;
		var j = 0;
    	
		for (var i = 0; i < items.length; i++) {
			curItem = items[i];
			// Make all children relative, even if not draggable
			if (curItem.nodeName == "DIV" && curItem.style.position != "relative")
				curItem.style.position = "relative";

			if (curItem.className == DragDrop.portletClassName) {
				if (!curItem.isStatic && !portletDraggingDisabled) {
					// if it's not static, make it moveable
					items2 = curItem.getElementsByTagName( "DIV" );
					foundHandle = false;

					for (j = 0; j < items2.length; j++) {
						if (items2[j].className == "portlet-title") {
							items2[j].style.cursor= "move";
							foundHandle = true;
							break;
						}
					}

					if (foundHandle)
						DragDrop.makeItemDragable(curItem, items2[j]);
				}
				else if (curItem.isStatic) {

					// otherwise, keep track of the static ones
					if (curItem.isStaticStart) {
						list.startPlaceholder = curItem;
					}

					else if (!list.endPlaceholder && curItem.isStaticEnd) {
						list.endPlaceholder = curItem;
					}
				}
			}
			else if (curItem.className && curItem.className.search("layout-blank") >= 0) {
				curItem.isStatic = true;
				curItem.isStaticEnd = true;
				curItem.isStaticStart = false;

				// count the bottom blank portlet as the end placeholder
				if (!list.endPlaceholder) {
					list.endPlaceholder = curItem;
				}
			}
		}
	},
        
	serData : function ( group, theid ) {
		var container = DragDrop.firstContainer;
		var j = 0;
		var string = "";
		var className = "";
		
		while (container != null) {
			if(theid != null && container.id != theid)
			{
			  container = container.nextContainer;
			  continue;
			}

			if(group != null && container.group != group)
			{
			  container = container.nextContainer;
			  continue;
			}
	
			j ++;
			if(j > 1)
			{
			  string += ":";
			}
			string += container.id;
			
			var items = container.getElementsByTagName( "DIV" );
			// Assume the 1st DIV is the dragable element
			string += "(";
			for (var i = 0; i < items.length; i++) {
				if (items[i].className == DragDrop.portletClassName) {
					if(i > 0)
					{
						string += ",";
					}
					string += items[i].id;
				}
			}
			string += ")";
					
			container = container.nextContainer;
		}
		return string;   
    },

	makeItemDragable : function(item, handle) {
		Drag.makeDraggable(item, handle);
		item.setDragThreshold(5);
		
		// tracks if the item is currently outside all containers
		item.isOutside = false;
		
		item.onDragStart = DragDrop.onDragStart;
		item.onDrag = DragDrop.onDrag;
		item.onDragEnd = DragDrop.onDragEnd;
	},

	onDragStart : function(nwPosition, sePosition, nwOffset, seOffset) {
		// update all container bounds, since they may have changed
		// on a previous drag
		// could be more smart about when to do this
		var container = DragDrop.firstContainer;
		while (container != null) {
			container.northwest = Coordinates.northwestOffset( container, true );
			container.southeast = Coordinates.southeastOffset( container, true );
			container = container.nextContainer;
		}
		
		// item starts out over current parent
		this.parentNode.className = this.parentNode.highlightClassName;
        parent_id = this.parentNode.id;
        parent_group = this.parentNode.group;
		// Keep track of original neighbor, so it can "snap" back later
		start_next = DragUtils.nextItem(this);
	},

	onDrag : function(nwPosition, sePosition, nwOffset, seOffset) {
		// check if we were nowhere
		if (this.isOutside) {
			// check each container to see if in its bounds
			var container = DragDrop.firstContainer;
			while (container != null) {

				if (nwOffset.inside( container.northwest, container.southeast )  && container.group == parent_group) {
					// we're inside this one
					container.className = container.highlightClassName;
					this.isOutside = false;
					
					// since isOutside was true, the current parent is a
					// temporary clone of some previous container node and
					// it needs to be removed from the document
					var tempParent = this.parentNode;
					tempParent.removeChild( this );
					container.appendChild( this );
					tempParent.parentNode.removeChild( tempParent );
					// Update boundaries
					container.southeast = Coordinates.southeastOffset( container, true );
					break;
				}
				container = container.nextContainer;
			}
			// we're still not inside the bounds of any container
			if (this.isOutside)
				return;
		
		// check if we're outside our parent's bounds
		}
		else if (!nwOffset.inside( this.parentNode.northwest, this.parentNode.southeast )) {
			
			this.parentNode.className = this.parentNode.defaultClassName;
			this.isOutside = true;
			
			// check if we're inside a new container's bounds
			var container = DragDrop.firstContainer;
			while (container != null) {
				if (nwOffset.inside( container.northwest, container.southeast ) && container.group == parent_group) {
					// we're inside this one
					container.className = container.highlightClassName;
					this.isOutside = false;
					this.parentNode.removeChild( this );
					container.appendChild( this );
					// Update boundaries
					container.southeast = Coordinates.southeastOffset( container, true );
					break;
				}
				container = container.nextContainer;
			}
			// if we're not in any container now, make a temporary clone of
			// the previous container node and add it to the document
			if (this.isOutside) {
				var tempParent = this.parentNode.cloneNode( false );
				this.parentNode.removeChild( this );
				tempParent.appendChild( this );
				// body puts a border or item at bottom of page if do
				// not have this
                tempParent.style.border = 0;
				document.getElementsByTagName( "body" ).item(0).appendChild( tempParent );
				return;
			}
		}
		
		// if we get here, we're inside some container bounds, so we do
		// everything the original dragsort script did to swap us into the
		// correct position
		
		var parent = this.parentNode;
				
		var item = this;
		var next = DragUtils.nextItem(item);

		while (next != null && this.offsetTop >= next.offsetTop - 2) {
			var item = next;
			var next = DragUtils.nextItem(item);
		}
		if (this != item && !item.isStatic) {
			DragUtils.swap(this, next);
			return;
		}

		var item = this;
		var previous = DragUtils.previousItem(item);
		if (next == null) {
			while (previous != null && previous.isStatic && previous.isStaticEnd) {
				item = previous;
				previous = DragUtils.previousItem(item);
				DragUtils.swap(this, item);
			}
		}
		while (previous != null && this.offsetTop <= previous.offsetTop + 2) {
			item = previous;
			previous = DragUtils.previousItem(item);
		}
		if (this != item && !item.isStatic) {
			DragUtils.swap(this, item);
			return;
		}
	},

	onDragEnd : function(nwPosition, sePosition, nwOffset, seOffset) {
		// if the drag ends and we're still outside all containers
		// it's time to remove ourselves from the document or add 
        // to the trash bin
		if (this.isOutside) {
			var container = DragDrop.firstContainer;
			while (container != null) {
			   if(container.id == parent_id)
			   {
				 break;
			   }
			   container = container.nextContainer;
			}
			this.isOutside = false;
			this.parentNode.removeChild( this );
			container.insertBefore( this, start_next );
            this.style["top"] = "0px";
		    this.style["left"] = "0px";
			return;
		}

		var position = 0;
		var positionFound = false;
		var container = DragDrop.firstContainer;
		var items = null;

		// Find the new position of the portlet
		while (container != null) {
			items = container.childNodes;
			position = 0;
			for (var i=0; i<items.length; i++) {
				if (items[i].className == DragDrop.portletClassName) {
					if (items[i].portletId == this.portletId) {
						positionFound = true;
						break;
					}
					if (!items[i].isStatic)
						position++;
				}
			}
			if (positionFound)
				break;

			container = container.nextContainer;
		}

		movePortlet(container.layoutId, this.portletId, container.columnOrder, position);

		this.parentNode.className = this.parentNode.defaultClassName;
      	this.style["top"] = "0px";
		this.style["left"] = "0px";
	}
};

var DragUtils = {
	swap : function(item1, item2) {
		var parent = item1.parentNode;
		parent.removeChild(item1);
		parent.insertBefore(item1, item2);

		item1.style["top"] = "0px";
		item1.style["left"] = "0px";
	},

	nextItem : function(item) {
		var sibling = item.nextSibling;
		while (sibling != null) {
			if (sibling.nodeName == item.nodeName) return sibling;
			sibling = sibling.nextSibling;
		}
		return null;
	},

	previousItem : function(item) {
		var sibling = item.previousSibling;
		while (sibling != null) {
			if (sibling.nodeName == item.nodeName) return sibling;
			sibling = sibling.previousSibling;
		}
		return null;
	}		
};

