var dnd = {
	initialize : function () {
		this.element = $('drag_dummy');
		this.elementImg = $('drag_dummy_img');
		this.elementText = $('drag_dummy_text');
		this.dropTargets = new Array ();
		this.draggedObj = null;
		this.currentDropTarget = null;
		this.dragging = false;
	},

	registerDrop: function (object) {
		this.dropTargets.push(object);
	},

	unregisterDrop: function (object) {
		this.dropTargets = this.dropTargets.without(object);
	},

	draggedIsOver: function (x,y, element) {
		/*var valueT = 0, valueL = 0;
		var el = element;
	    do {
			if(el.style.position == 'fixed') {
				valueT += window.pageYOffset + el.offsetTop;
				valueL += window.pageXOffset + el.offsetLeft;
				el= null;
			} else {
				valueT += el.offsetTop  || 0;
				valueL += el.offsetLeft || 0;
				el= el.offsetParent;
			}
	    } while (el);

	    return (y >= valueT &&
            y <  valueT + element.offsetHeight &&
            x >= valueL &&
            x <  valueL + element.offsetWidth);*/
		Position.prepare();
		Position.includeScrollOffsets = true;
		var deltaX =  window.pageXOffset
                || document.documentElement.scrollLeft
                || document.body.scrollLeft
                || 0;
        var deltaY =  window.pageYOffset
                || document.documentElement.scrollTop
                || document.body.scrollTop
                || 0;
		return Position.within(element, x - deltaX, y - deltaY);
		//return Position.within(element, x, y);
	},

	startDragging: function (event, draggedObject, onSuccess) {
		//if (this.dropTargets.length < 1) return;
		this.onSuccess = onSuccess; // this is a function to be calles when dragging is over
		this.draggedObj = draggedObject;
		this.currentDropTarget = null;
		this.dragging = true;
		this.elementText.innerHTML = '';
		this.element.style.display = 'block';
		this.element.style.left = Event.pointerX(event) + 'px';
		this.element.style.top = Event.pointerY(event) + 'px';
		document.body.style.cursor = "pointer";
		Event.stop(event);

		this.eventMouseUp   = this.endDragging.bindAsEventListener(this);
    	this.eventMouseMove = this.updateDragging.bindAsEventListener(this);
		Event.observe(document, "mouseup", this.eventMouseUp);
  		Event.observe(document, "mousemove", this.eventMouseMove);
	},

	updateDragging: function (event) {
		if (!this.dragging) return;

		Event.stop(event);
		var nx = Event.pointerX(event);
		var ny = Event.pointerY(event);

		this.element.style.top = ny + 'px';
		this.element.style.left = nx + 'px';


		var newDropTarget = null;
		// we go down the array, because if we have two overlaping drop areas,
		// the seccond added gets the drop
		for (var i = this.dropTargets.length - 1; i >=0 ; i --) {
			if (this.draggedIsOver(nx,ny, this.dropTargets[i].element)) {
				newDropTarget = this.dropTargets[i];
				break;
			}
		}
		if (newDropTarget == null) {
			//not over any registered drop zone
			if (this.currentDropTarget != null)
				this.currentDropTarget.dragUnhover();
			this.elementText.innerHTML = '';
			this.currentDropTarget = null;
			return;
		}

		if (newDropTarget == this.currentDropTarget && newDropTarget != null) {
			this.currentDropTarget.dragHover(event, this.draggedObj);
			return;
		}

		if (newDropTarget != this.currentDropTarget) {
			if (this.currentDropTarget != null && this.currentDropTarget.dragUnhover)
				this.currentDropTarget.dragUnhover();
			this.elementText.innerHTML = 'drop me...';
			this.currentDropTarget = newDropTarget;
			this.currentDropTarget.dragHover(event, this.draggedObj);
		}
	},

	endDragging: function (event) {
		if (!this.dragging) return;
		document.body.style.cursor = "";
		Event.stop(event);
		this.dragging = false;
		this.element.style.display = 'none';

		if (this.currentDropTarget != null) {
			if (this.currentDropTarget.recieveDrag)
				this.currentDropTarget.recieveDrag(this.draggedObj);
			if (this.onSuccess)
				this.onSuccess(this.draggedObj, this.currentDropTarget);
		}

		this.currentDropTarget = null;
		this.draggedObj = null;

		Event.stopObserving(document, "mouseup", this.endDragging);
  		Event.stopObserving(document, "mousemove", this.updateDragging);
	},

	getOverlap: function (event, mode, element) { //when an element receives the drag, it can call this
		if (arguments.length == 2) var element = this.currentDropTarget.element;
		Position.prepare();
		Position.includeScrollOffsets = true;
		var deltaX =  window.pageXOffset
                || document.documentElement.scrollLeft
                || document.body.scrollLeft
                || 0;
        var deltaY =  window.pageYOffset
                || document.documentElement.scrollTop
                || document.body.scrollTop
                || 0;
       	Position.within(element, Event.pointerX(event) - deltaX, Event.pointerY(event) - deltaY); // just to setup the Position object

        return Position.overlap(mode,element);
	},

	setText: function (text) {
		this.elementText.innerHTML = text;
	},
	setImage: function (src) {
		this.elementImg.src = src;
	}
}