/*
	Copyright (c) 2004-2006, The Dojo Foundation
	All Rights Reserved.

	Licensed under the Academic Free License version 2.1 or above OR the
	modified BSD license. For more information on Dojo licensing, see:

		http://dojotoolkit.org/community/licensing.shtml
*/

dojo.provide("dojo.dnd.HtmlDragAndDrop");

dojo.require("dojo.dnd.HtmlDragManager");
dojo.require("dojo.dnd.DragAndDrop");

dojo.require("dojo.html.*");
dojo.require("dojo.html.display");
dojo.require("dojo.html.util");
dojo.require("dojo.html.selection");
dojo.require("dojo.html.iframe");
dojo.require("dojo.lang.extras");
dojo.require("dojo.lfx.*");
dojo.require("dojo.event.*");

dojo.declare("dojo.dnd.HtmlDragSource", dojo.dnd.DragSource, {
		dragClass: "", // CSS classname(s) applied to node when it is being dragged

		onDragStart: function(){
			var dragObj = new dojo.dnd.HtmlDragObject(this.dragObject, this.type);
			if(this.dragClass){
				dragObj.dragClass = this.dragClass;
			}

			if(this.constrainToContainer){
				dragObj.constrainTo(this.constrainingContainer || this.domNode.parentNode);
			}

			return dragObj;
		},

		setDragHandle: function(node){
			node = dojo.byId(node);
			dojo.dnd.dragManager.unregisterDragSource(this);
			this.domNode = node;
			dojo.dnd.dragManager.registerDragSource(this);
		},

		setDragTarget: function(node){
			this.dragObject = node;
		},

		constrainTo: function(container){
			this.constrainToContainer = true;
			if(container){
				this.constrainingContainer = container;
			}
		},

		/*
		*
		* see dojo.dnd.DragSource.onSelected
		*/
		onSelected: function(){
			for(var i=0; i<this.dragObjects.length; i++){
				dojo.dnd.dragManager.selectedSources.push(new dojo.dnd.HtmlDragSource(this.dragObjects[i]));
			}
		},

		/**
		* Register elements that should be dragged along with
		* the actual DragSource.
		*
		* Example usage:
		* 	var dragSource = new dojo.dnd.HtmlDragSource(...);
		*	// add a single element
		*	dragSource.addDragObjects(dojo.byId('id1'));
		*	// add multiple elements to drag along
		*	dragSource.addDragObjects('id2', dojo.byId('id3'));
		*
		* el A dom node to add to the drag list.
		*/
		addDragObjects: function(/*DOMNode*/ el){
			for(var i=0; i<arguments.length; i++){
				this.dragObjects.push(dojo.byId(arguments[i]));
			}
		}
	},

	function(node, type){
		node = dojo.byId(node);
		this.dragObjects = [];
		this.constrainToContainer = false;
		if(node){
			this.domNode = node;
			this.dragObject = node;
			// set properties that might have been clobbered by the mixin
			this.type = (type)||(this.domNode.nodeName.toLowerCase());
			dojo.dnd.DragSource.prototype.reregister.call(this);
		}
	}
);

dojo.declare("dojo.dnd.HtmlDragObject",
	dojo.dnd.DragObject,
	{
		dragClass: "",
		opacity: 0.5,
		createIframe: true,		// workaround IE6 bug

		// if true, node will not move in X and/or Y direction
		disableX: false,
		disableY: false,

		createDragNode: function() {
			var node = this.domNode.cloneNode(true);
			if(this.dragClass) { dojo.html.addClass(node, this.dragClass); }
			if(this.opacity < 1) { dojo.html.setOpacity(node, this.opacity); }
			var ltn = node.tagName.toLowerCase();
			var isTr = (ltn == "tr");
			if((isTr)||(ltn == "tbody")){
				// dojo.debug("Dragging table row")
				// Create a table for the cloned row
				var doc = this.domNode.ownerDocument;
				var table = doc.createElement("table");
				if(isTr){
					var tbody = doc.createElement("tbody");
					table.appendChild(tbody);
					tbody.appendChild(node);
				}else{
					table.appendChild(node);
				}

				// Set a fixed width to the cloned TDs
				var tmpSrcTr = ((isTr) ? this.domNode : this.domNode.firstChild);
				var tmpDstTr = ((isTr) ? node : node.firstChild);
				var domTds = tdp.childNodes;
				var cloneTds = tmpDstTr.childNodes;
				for(var i = 0; i < domTds.length; i++){
					if((cloneTds[i])&&(cloneTds[i].style)){
						cloneTds[i].style.width = dojo.html.getContentBox(domTds[i]).width + "px";
					}
				}
				node = table;
			}

			if((dojo.render.html.ie55||dojo.render.html.ie60) && this.createIframe){
				with(node.style) {
					top="0px";
					left="0px";
				}
				var outer = document.createElement("div");
				outer.appendChild(node);
				this.bgIframe = new dojo.html.BackgroundIframe(outer);
				outer.appendChild(this.bgIframe.iframe);
				node = outer;
			}
			node.style.zIndex = 999;

			return node;
		},

		onDragStart: function(e){
			dojo.html.clearSelection();

			this.scrollOffset = dojo.html.getScroll().offset;
			this.dragStartPosition = dojo.html.getAbsolutePosition(this.domNode, true);

			this.dragOffset = {y: this.dragStartPosition.y - e.pageY,
				x: this.dragStartPosition.x - e.pageX};

			this.dragClone = this.createDragNode();

			this.containingBlockPosition = this.domNode.offsetParent ?
				dojo.html.getAbsolutePosition(this.domNode.offsetParent, true) : {x:0, y:0};

			if(this.constrainToContainer){
				this.constraints = this.getConstraints();
			}

			// set up for dragging
			with(this.dragClone.style){
				position = "absolute";
				top = this.dragOffset.y + e.pageY + "px";
				left = this.dragOffset.x + e.pageX + "px";
			}

			dojo.body().appendChild(this.dragClone);

			dojo.event.topic.publish('dragStart', { source: this } );
		},

		/** Return min/max x/y (relative to document.body) for this object) **/
		getConstraints: function(){
			if(this.constrainingContainer.nodeName.toLowerCase() == 'body'){
				var viewport = dojo.html.getViewport();
				var width = viewport.width;
				var height = viewport.height;
				var scroll = dojo.html.getScroll().offset;
				var x = scroll.x;
				var y = scroll.y;
			}else{
				var content = dojo.html.getContentBox(this.constrainingContainer);
				width = content.width;
				height = content.height;
				x =
					this.containingBlockPosition.x +
					dojo.html.getPixelValue(this.constrainingContainer, "padding-left", true) +
					dojo.html.getBorderExtent(this.constrainingContainer, "left");
				y =
					this.containingBlockPosition.y +
					dojo.html.getPixelValue(this.constrainingContainer, "padding-top", true) +
					dojo.html.getBorderExtent(this.constrainingContainer, "top");
			}

			// TODO: should handle left/top/right/bottom margin separately; left/top should affect minX/minY
			var mb = dojo.html.getMarginBox(this.domNode);
			return {
				minX: x,
				minY: y,
				maxX: x + width - mb.width,
				maxY: y + height - mb.height
			}
		},

		updateDragOffset: function(){
			var scroll = dojo.html.getScroll().offset;
			if(scroll.y != this.scrollOffset.y){
				var diff = scroll.y - this.scrollOffset.y;
				this.dragOffset.y += diff;
				this.scrollOffset.y = scroll.y;
			}
			if(scroll.x != this.scrollOffset.x){
				var diff = scroll.x - this.scrollOffset.x;
				this.dragOffset.x += diff;
				this.scrollOffset.x = scroll.x;
			}
		},

		/** Moves the node to follow the mouse */
		onDragMove: function(e){
			this.updateDragOffset();
			var x = this.dragOffset.x + e.pageX;
			var y = this.dragOffset.y + e.pageY;

			if (this.constrainToContainer) {
				if (x < this.constraints.minX) { x = this.constraints.minX; }
				if (y < this.constraints.minY) { y = this.constraints.minY; }
				if (x > this.constraints.maxX) { x = this.constraints.maxX; }
				if (y > this.constraints.maxY) { y = this.constraints.maxY; }
			}

			this.setAbsolutePosition(x, y);

			dojo.event.topic.publish('dragMove', { source: this } );
		},

		/**
		 * Set the position of the drag clone.  (x,y) is relative to <body>.
		 */
		setAbsolutePosition: function(x, y){
			// The drag clone is attached to document.body so this is trivial
			if(!this.disableY) { this.dragClone.style.top = y + "px"; }
			if(!this.disableX) { this.dragClone.style.left = x + "px"; }
		},


		/**
		 * If the drag operation returned a success we remove the clone of
		 * ourself from the original position. If the drag operation returned
		 * failure we slide back over to where we came from and end the operation
		 * with a little grace.
		 */
		onDragEnd: function(e){
			switch(e.dragStatus){

				case "dropSuccess":
					dojo.html.removeNode(this.dragClone);
					this.dragClone = null;
					break;

				case "dropFailure": // slide back to the start
					var startCoords = dojo.html.getAbsolutePosition(this.dragClone, true);
					// offset the end so the effect can be seen
					var endCoords = { left: this.dragStartPosition.x + 1,
						top: this.dragStartPosition.y + 1};

					// animate
					var anim = dojo.lfx.slideTo(this.dragClone, endCoords, 300);
					var dragObject = this;
					dojo.event.connect(anim, "onEnd", function(e){
						// pause for a second (not literally) and disappear
						// dojo.lang.setTimeout(function() {
								dojo.html.removeNode(dragObject.dragClone);
								// Allow drag clone to be gc'ed
								dragObject.dragClone = null;
						// 	},
						// 	50);
					});
					anim.play();
					break;
			}

			dojo.event.topic.publish('dragEnd', { source: this } );
		},

		constrainTo: function(container){
			this.constrainToContainer=true;
			if(container){
				this.constrainingContainer = container;
			}else{
				this.constrainingContainer = this.domNode.parentNode;
			}
		}
	},
	function(node, type){
		this.domNode = dojo.byId(node);
		this.type = type;
		this.constrainToContainer = false;
		this.dragSource = null;
		// this.register();
		dojo.dnd.DragObject.prototype.register.call(this);
	}
);

dojo.declare("dojo.dnd.HtmlDropTarget",
	dojo.dnd.DropTarget,
	{
		vertical: false,
		onDragOver: function(e){
			if(!this.accepts(e.dragObjects)){ return false; }

			// cache the positions of the child nodes
			this.childBoxes = [];
			for(var i = 0, child; i < this.domNode.childNodes.length; i++){
				child = this.domNode.childNodes[i];
				if(child.nodeType != dojo.html.ELEMENT_NODE){ continue; }
				var pos = dojo.html.getAbsolutePosition(child, true);
				var inner = dojo.html.getBorderBox(child);
				this.childBoxes.push({top: pos.y, bottom: pos.y+inner.height,
					left: pos.x, right: pos.x+inner.width, height: inner.height,
					width: inner.width, node: child});
			}

			// TODO: use dummy node

			return true;
		},

		_getNodeUnderMouse: function(e){
			// find the child
			for(var i = 0, child; i < this.childBoxes.length; i++){
				with(this.childBoxes[i]){
					if (e.pageX >= left && e.pageX <= right &&
						e.pageY >= top && e.pageY <= bottom){ return i; }
				}
			}

			return -1;
		},

		createDropIndicator: function(){
			this.dropIndicator = document.createElement("div");
			with(this.dropIndicator.style){
				position = "absolute";
				zIndex = 999;
				if(this.vertical){
					borderLeftWidth = "1px";
					borderLeftColor = "black";
					borderLeftStyle = "solid";
					height = dojo.html.getBorderBox(this.domNode).height + "px";
					top = dojo.html.getAbsolutePosition(this.domNode, true).y + "px";
				}else{
					borderTopWidth = "1px";
					borderTopColor = "black";
					borderTopStyle = "solid";
					width = dojo.html.getBorderBox(this.domNode).width + "px";
					left = dojo.html.getAbsolutePosition(this.domNode, true).x + "px";
				}
			}
		},

		onDragMove: function(e, dragObjects){
			var i = this._getNodeUnderMouse(e);

			if(!this.dropIndicator){
				this.createDropIndicator();
			}

			var gravity = this.vertical ? dojo.html.gravity.WEST : dojo.html.gravity.NORTH;
			var hide = false;
			if(i < 0){
				if(this.childBoxes.length){
					var before = (dojo.html.gravity(this.childBoxes[0].node, e) & gravity);
					if(before){ hide = true; }
				}else{
					var before = true;
				}
			}else{
				var child = this.childBoxes[i];
				var before = (dojo.html.gravity(child.node, e) & gravity);
				if(child.node === dragObjects[0].dragSource.domNode){
					hide = true;
				}else{
					var currentPosChild = before ?
							(i>0?this.childBoxes[i-1]:child) :
							(i<this.childBoxes.length-1?this.childBoxes[i+1]:child);
					if(currentPosChild.node === dragObjects[0].dragSource.domNode){
						hide = true;
					}
				}
			}

			if(hide){
				this.dropIndicator.style.display="none";
				return;
			}else{
				this.dropIndicator.style.display="";
			}

			this.placeIndicator(e, dragObjects, i, before);

			if(!dojo.html.hasParent(this.dropIndicator)) {
				dojo.body().appendChild(this.dropIndicator);
			}
		},

		/**
		 * Position the horizontal line that indicates "insert between these two items"
		 */
		placeIndicator: function(e, dragObjects, boxIndex, before) {
			var targetProperty = this.vertical ? "left" : "top";
			var child;
			if(boxIndex < 0){
				if(this.childBoxes.length){
					child = before ? this.childBoxes[0]
						: this.childBoxes[this.childBoxes.length - 1];
				}else{
					this.dropIndicator.style[targetProperty] = dojo.html.getAbsolutePosition(this.domNode, true)[this.vertical?"x":"y"] + "px";
				}
			}else{
				child = this.childBoxes[boxIndex];
			}
			if(child){
				this.dropIndicator.style[targetProperty] = (before ? child[targetProperty] : child[this.vertical?"right":"bottom"]) + "px";
				if(this.vertical){
					this.dropIndicator.style.height = child.height + "px";
					this.dropIndicator.style.top = child.top + "px";
				}else{
					this.dropIndicator.style.width = child.width + "px";
					this.dropIndicator.style.left = child.left + "px";
				}
			}
		},

		onDragOut: function(e) {
			if(this.dropIndicator) {
				dojo.html.removeNode(this.dropIndicator);
				delete this.dropIndicator;
			}
		},

		/**
		 * Inserts the DragObject as a child of this node relative to the
		 * position of the mouse.
		 *
		 * @return true if the DragObject was inserted, false otherwise
		 */
		onDrop: function(e){
			this.onDragOut(e);

			var i = this._getNodeUnderMouse(e);

			var gravity = this.vertical ? dojo.html.gravity.WEST : dojo.html.gravity.NORTH;
			if(i < 0){
				if(this.childBoxes.length){
					if(dojo.html.gravity(this.childBoxes[0].node, e) & gravity){
						return this.insert(e, this.childBoxes[0].node, "before");
					}else{
						return this.insert(e, this.childBoxes[this.childBoxes.length-1].node, "after");
					}
				}
				return this.insert(e, this.domNode, "append");
			}

			var child = this.childBoxes[i];
			if(dojo.html.gravity(child.node, e) & gravity){
				return this.insert(e, child.node, "before");
			}else{
				return this.insert(e, child.node, "after");
			}
		},

		insert: function(e, refNode, position){
			var node = e.dragObject.domNode;

			if(position == "before"){
				return dojo.html.insertBefore(node, refNode);
			}else if(position == "after"){
				return dojo.html.insertAfter(node, refNode);
			}else if(position == "append"){
				refNode.appendChild(node);
				return true;
			}

			return false;
		}
	},

	function(node, types){
		if(arguments.length == 0){ return; }
		this.domNode = dojo.byId(node);
		dojo.dnd.DropTarget.call(this);
		if(types && dojo.lang.isString(types)) {
			types = [types];
		}
		this.acceptedTypes = types || [];
		dojo.dnd.dragManager.registerDropTarget(this);
	}
);
