// common.js compatible

sortable = {
	dragging: false,
	drag_elem: null,
	list: null,
	xOff: 0,
	yOff: 0,
	sortHelper: null,

	makeSortable: function(elem, drag) {
		var dragtargets = {nodes:[]};
		if(drag && drag.target){
			var nodes = drag.target.childNodes;
			for (var i in nodes) {
				if (nodes[i].nodeType == 1)  {
					dragtargets.nodes.push(nodes[i]);
				}
			}
			dragtargets.ondragover = drag.ondragover;
			dragtargets.ondragout = drag.ondragout;
			dragtargets.ondragend = drag.ondragend;
		}
		var nodes = elem.childNodes;
		for (var i in nodes) {
			if (nodes[i].nodeType == 1)  {
				nodes[i]._sortable = true;
				if(dragtargets.nodes.length>0)nodes[i]._dragtargets = dragtargets;
				nodes[i]._width = nodes[i].offsetWidth;
				nodes[i]._height = nodes[i].offsetHeight;
				var xy = getXY(nodes[i]);
				nodes[i]._x = xy[0] - nodes[i].offsetLeft;
				nodes[i]._y = xy[1] - nodes[i].offsetTop;
				nodes[i]._xright = nodes[i]._x + nodes[i]._width;
				nodes[i]._ybottom = nodes[i]._y + nodes[i]._height;
				addEvent(nodes[i], "mousedown", this.mousedown.bind(this));
				addEvent(nodes[i], "mousemove", this.mousemove.bind(this));
				addEvent(nodes[i], "mouseup", this.mouseup.bind(this));
			}
		}
	},

	findNode: function(elem) {
		do {
			if (elem._sortable)
				return elem;
			elem = elem.parentNode;
		} while(elem.parentNode != false);				
		return null;
	},

	updatePos: function(elem, event) {
		elem.style.left = event.pageX - this.xOff + "px";
		elem.style.top = event.pageY - this.yOff + "px";
	},

	mousedown: function(event) {
		if (this.dragging)
			return;
		var target = event.srcElement || event.target;
		if (target.tagName == "A" || target.tagName == "INPUT" || target.getAttribute("nosorthandle"))
			return;
		var elem = this.findNode(target);
		var xy = getXY(elem);
		this.xOff = event.pageX - xy[0];
		this.yOff = event.pageY - xy[1];
		css.pushStyles(elem, {"width": elem.style.width || (elem.offsetWidth + "px"), "zIndex": "10000", "left": elem.style.left || "", "top": elem.style.top || ""});
		elem._width = elem.offsetWidth;
		elem._height = elem.offsetHeight;
		this.updatePos(elem, event);
		var t = elem.ownerDocument.createElement("DIV");
		t.innerHTML = '&nbsp; ';
		t.style.height = elem._height - 2 + "px";
		t.style.width = elem._width - 2 + "px";
		t.style.border = "1px dashed #D8DFEA";
		t.style.cssFloat = elem.style.cssFloat || "";
		t.style.styleFloat = elem.style.styleFloat || "";
		this.sortHelper = t;
 		this.list = elem.parentNode;
   	if (this.list.onSortBegin){
        var allowBegin = (this.list.onSortBegin.bind(this))(elem);
        if(allowBegin !== undefined && !allowBegin)return;
       }
		this.dragging = true;
		this.drag_elem = elem;		
		addEvent(document, "mousemove", this.mousemove.bind(this));
		addEvent(document, "drag", this.mousemove.bind(this));
		addEvent(document, "mouseup", this.mouseup.bind(this));
		this.list.insertBefore(t, elem);
		css.pushStyles(elem, {"position": "absolute"});

		var nodes = this.list.childNodes, n = nodes.length;
		var dir = 1, before = true;

		return cancelEvent(event);
	},

	mousemove: function(event, wheel) {
		if (!this.dragging)
			return;
		var elem = this.drag_elem;
		this.updatePos(elem, event);	
		var nodes = this.list.childNodes, n = nodes.length;
		var dir = 1, before = true;
		var mouseX = event.pageX, mouseY = event.pageY;
		if(elem._dragtargets){
			for(var i in elem._dragtargets.nodes){
				var dragtarget = elem._dragtargets.nodes[i];
				var xy = getXY(dragtarget);
				var p1 = {x:(mouseX - xy[0]), y:(mouseY - xy[1])};
				if(p1.x > 0 && p1.x < dragtarget.offsetWidth && p1.y > 0 && p1.y < dragtarget.offsetHeight){
					if(!dragtarget._dragover){
						if(elem._dragtargets.ondragover)elem._dragtargets.ondragover(elem, dragtarget);
						dragtarget._dragover = true;
						elem._dragtarget = dragtarget;
					}
				}else if(dragtarget._dragover){
					if(elem._dragtargets.ondragout)elem._dragtargets.ondragout(elem, dragtarget);
					dragtarget._dragover = false;
					elem._dragtarget = null;
				}
			}
		}
		var wBuffer = 0, hBuffer = 0;
		for(var i = 0; ; i += dir) {
			var itm = nodes[i];
			if (itm == this.sortHelper) {
				if (dir == 1) {
					i = n;
					dir = -1;
					before = false;
					continue;
				} else 
					break;
			}
			if (itm.nodeType == 3 || itm == elem)
				continue;
			if (before) {
				if (mouseX <= itm._xright + itm.offsetLeft && mouseY <= itm._ybottom + itm.offsetTop) {
					this.list.removeChild(this.sortHelper);
					this.list.insertBefore(this.sortHelper, itm);
					break;
				}
			} else {
				wBuffer = elem._width < itm._width ? itm._width - elem._width : 0;
				hBuffer = elem._height < itm._height ? itm._height - elem._height : 0;
				if (mouseX > itm._x + itm.offsetLeft + wBuffer && mouseY > itm._y + itm.offsetTop + hBuffer) {
					this.list.removeChild(this.sortHelper);
					this.list.insertBefore(this.sortHelper, itm.nextSibling);
					break;
				}
			}
		}
		if (!wheel)
			return cancelEvent(event);
		return true;
	},

	mouseup: function(event) {
		if (!this.dragging)
			return;				
		var elem = this.drag_elem;
		this.list.removeChild(elem);
		this.list.insertBefore(elem, this.sortHelper);
		this.list.removeChild(this.sortHelper);
		this.sortHelper = null;
		css.popStyles(elem, ["width", "position", "zIndex", "left", "top"]);
		this.dragging = false;
		this.drag_elem = null;
		removeEvent(document, "mousemove");
		removeEvent(document, "drag");
		removeEvent(document, "mouseup");
		if(elem._dragtarget){
			if(elem._dragtargets.ondragout)elem._dragtargets.ondragout(elem, elem._dragtarget);
			if(elem._dragtargets.ondragend)elem._dragtargets.ondragend(elem, elem._dragtarget);
		}
    	else if (elem.parentNode.onSortEnd)
			elem.parentNode.onSortEnd(elem);
		return cancelEvent(event);
	}
}

//old
css = {
	pushStyles: function(obj, styles) {
		for(i in styles) {
			obj["_style"+ i] = obj.style[i] || "";
			obj.style[i] = styles[i];
		}
	},

	popStyles: function(obj, styles) {
		for(i = 0; i < styles.length; i++)
			obj.style[styles[i]] = obj["_style"+ styles[i]];
	}
	
	/*
	getStyleInt: function(obj, style){
		var value = getStyle(obj, style);
		var res = parseInt(value, 10);
		if(!isNaN(res))return res;
		if(value=="thin")return 2;
		if(value=="medium")return 4;
		if(value=="thick")return 6;
		return 0;
	},

	getPureWidth: function(obj) {
		return obj.offsetWidth;
		return obj.offsetWidth - css.getStyleInt(obj, "borderLeftWidth") - css.getStyleInt(obj, "paddingLeft") - css.getStyleInt(obj, "paddingRight") - css.getStyleInt(obj, "borderRightWidth");
	}
	*/
}
