load('positioning')
load('mouse');
load('number');

(function dragDropNamespace(){
	var mouseOffset = null;
	var iMouseDown  = false;
	var lMouseState = false;
	var dragObject  = null;

	var DragDrops   = [];
	var curTarget   = null;
	var lastTarget  = null;
	var dragHelper  = null;
	var tempDiv     = null;
	var rootParent  = null;
	var rootSibling = null;
	var ix = 0;

	function cDC(){
		var cDrag        = DragDrops.length;
		DragDrops[cDrag] = [];

		for(var i=0; i<arguments.length; i++){
			var cObj = arguments[i];
			DragDrops[cDrag].push(cObj);
			cObj.setAttribute('DropObj', cDrag);

			for(var j=0; j<cObj.childNodes.length; j++){
				if(cObj.childNodes[j].nodeName=='#text') continue;
				cObj.childNodes[j].setAttribute('DragObj', cDrag);
			}
		}

		return cDrag;
	}

	function mouseMove(ev){
		ev         = ev || _w.event;

		var target   = ev.target || ev.srcElement;
		var mousePos = mouseCoords(ev);

		if(lastTarget && (target!==lastTarget)){
			// reset the classname for the target element
			var origClass = lastTarget.getAttribute('origClass');
			if(origClass) lastTarget.className = origClass;
		}

		var dragObj;
		while(!dragObj && target && target.getAttribute){
			target  = target.parentNode;
			if(!target || !target.getAttribute) break;
			dragObj = target.getAttribute('DragObj');
		}
		if(!dragObj) target = _;

		if(dragObj && target){
			if(target!=lastTarget){
				var oClass = target.getAttribute('overClass');
				if(oClass){
					target.setAttribute('origClass', target.className);
					target.className = oClass;
				}
			}

			if(iMouseDown && !lMouseState){
				curTarget     = target;

				rootParent    = curTarget.parentNode;
				rootSibling   = curTarget.nextSibling;

				mouseOffset   = getMouseOffset(target, ev);

				for(var i=0; i<dragHelper.childNodes.length; i++) dragHelper.removeChild(dragHelper.childNodes[i]);

				dragHelper.appendChild(curTarget.cloneNode(true));
				dragHelper.style.width   = parseInt(curTarget.offsetWidth)+'px';
				dragHelper.style.display = 'block';

				var dragClass = curTarget.getAttribute('dragClass');
				if(dragClass){
					dragHelper.firstChild.className = dragClass;
				}

				dragHelper.firstChild.removeAttribute('DragObj');

				var dragConts = DragDrops[dragObj];

				curTarget.setAttribute('startWidth',  parseInt(curTarget.offsetWidth));
				curTarget.setAttribute('startHeight', parseInt(curTarget.offsetHeight));
				curTarget.style.display  = 'none';

				for(var i=0; i<dragConts.length; i++){
					with(dragConts[i]){
						var pos = getPosition(dragConts[i]);

						setAttribute('startWidth',  parseInt(offsetWidth));
						setAttribute('startHeight', parseInt(offsetHeight));
						setAttribute('startLeft',   pos.x);
						setAttribute('startTop',    pos.y);
					}

					for(var j=0; j<dragConts[i].childNodes.length; j++){
						with(dragConts[i].childNodes[j]){
							if((nodeName=='#text') || (dragConts[i].childNodes[j]==curTarget)) continue;

							var pos = getPosition(dragConts[i].childNodes[j]);

							setAttribute('startWidth',  parseInt(offsetWidth));
							setAttribute('startHeight', parseInt(offsetHeight));
							setAttribute('startLeft',   pos.x);
							setAttribute('startTop',    pos.y);
						}
					}
				}
			}
		}

		if(curTarget){
			dragHelper.style.top  = (mousePos.y - mouseOffset.y) + 'px';
			dragHelper.style.left = (mousePos.x - mouseOffset.x) + 'px';

			var dragConts  = DragDrops[curTarget.getAttribute('DragObj')];
			var activeCont = null;

			var xPos = mousePos.x - mouseOffset.x + (parseInt(curTarget.getAttribute('startWidth')) /2);
			var yPos = mousePos.y - mouseOffset.y + (parseInt(curTarget.getAttribute('startHeight'))/2);

			for(var i=0; i<dragConts.length; i++){
				with(dragConts[i]){
					if((parseInt(getAttribute('startLeft'))                                           < xPos) &&
						(parseInt(getAttribute('startTop'))                                            < yPos) &&
						((parseInt(getAttribute('startLeft')) + parseInt(getAttribute('startWidth')))  > xPos) &&
						((parseInt(getAttribute('startTop'))  + parseInt(getAttribute('startHeight'))) > yPos)){

							activeCont = dragConts[i];

							break;
					}
				}
			}

			if(activeCont){
				var beforeNode = null;

				for(var i=activeCont.childNodes.length-1; i>=0; i--){
					with(activeCont.childNodes[i]){
						if(nodeName=='#text') continue;

						if(curTarget != activeCont.childNodes[i]                                                  &&
							((parseInt(getAttribute('startLeft')) + parseInt(getAttribute('startWidth')))  > xPos) &&
							((parseInt(getAttribute('startTop'))  + parseInt(getAttribute('startHeight'))) > yPos)){
								beforeNode = activeCont.childNodes[i];
						}
					}
				}

				if(beforeNode){
					if(beforeNode!=curTarget.nextSibling){

						activeCont.insertBefore(curTarget, beforeNode);
					}
				} else {
					if((curTarget.nextSibling) || (curTarget.parentNode!=activeCont)){

						activeCont.appendChild(curTarget);
					}
				}

				setTimeout(function(){
				var contPos = getPosition(activeCont);
				activeCont.setAttribute('startWidth',  parseInt(activeCont.offsetWidth));
				activeCont.setAttribute('startHeight', parseInt(activeCont.offsetHeight));
				activeCont.setAttribute('startLeft',   contPos.x);
				activeCont.setAttribute('startTop',    contPos.y);}, 5);

				if(curTarget.style.display!=''){
					curTarget.style.display    = '';
					curTarget.style.visibility = 'hidden';
				}
			} else {
				if(curTarget.style.display!='none'){
					curTarget.style.display  = 'none';
				}
			}
		}

		lMouseState = iMouseDown;
		lastTarget  = target;
		lMouseState = iMouseDown;

		if(curTarget || dragObject) return false;
	}

	function mouseUp(ev){
		if(curTarget){
			dragHelper.style.display = 'none';

			if(curTarget.style.display == 'none'){
				if(rootSibling){
					rootParent.insertBefore(curTarget, rootSibling);
				} else {
					rootParent.appendChild(curTarget);
				}
			}

			curTarget.style.display = '';
			curTarget.style.visibility = 'visible';

			if(rootParent.getAttribute('ondragend')) eval(rootParent.getAttribute('ondragend')).bind(rootParent)();
		}
		curTarget  = null;
		iMouseDown = false;
	}

	function mouseDown(){
		iMouseDown = true;
		if(lastTarget){
			return false;
		}
	}

	function getMouseOffset(target, ev){
		ev = ev || _w.event;

		var docPos    = getPosition(target);
		var mousePos  = mouseCoords(ev);
		return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};
	}

	addEvent(_d, 'mousemove', mouseMove);
	addEvent(_d, 'mousedown', mouseDown);
	addEvent(_d, 'mouseup',   mouseUp);

	addLoadEvent(function(){
		dragHelper = cE('DIV');
		dragHelper.id = 'dragHelper';
		dragHelper.style.cssText = 'position:absolute;display:none;';

		_d.body.appendChild(dragHelper);
	});

	_w.createDragContainer = cDC;
})();

