var DragDropElements = new Array();
// TODO: clear DragDropElements, maybe every time we refresh the folders

var GlobalDragObject = false;
var GlobalDropObject = false;

/*
 *	=============================
 *    CLASS DragObject
 *	=============================
 */

function DragObject(){
	this.DDElement = false;
	// Create DOMElement
	var DOMElement = document.createElement('div');
	DOMElement.id = "DragObject";
	DOMElement.style.position = "absolute";
	DOMElement.style.opacity = "0.7";
	//DOMElement.style.background = "yellow";
	DOMElement.style.display = "none";
	DOMElement.style.zIndex = "9999";
	document.getElementsByTagName('body')[0].appendChild(DOMElement);
	this.DOMElement = DOMElement;
	// Init position
	this.top = 0;
	this.left = 0;
	this.bottom = 0;
	this.right = 0;
	this.width = 0;
	this.height = 0;

	// make DragObject clickable
	DOMElement.onmousedown = function(ev){
		ev = ev || window.event;
		var DragObject = getDragObject();
		DragObject.startDragging(ev);
	}

	// Hide DragObject onmouseout
	DOMElement.onmouseout = function(ev){
		ev = ev || window.event;
		var DragObject = getDragObject();
		if(DragObject.dragging) return;
		DragObject.clearDragObject();
	}

	DOMElement.onclick = function(ev){
		ev = ev || window.event;
		var DragObject = getDragObject();
		if(DragObject.DDElement.handleClick)
			DragObject.DDElement.handleClick();
	}
}

DragObject.prototype.setupDragObject = function(DDElement){
	// Clone DDElement
	DDElement.calcPosition();
	this.DDElement = DDElement;
	// remove all DOM ids to keep ids unique
	this.DOMElement.innerHTML = this.stripIds(DDElement.DOMElement.innerHTML);
	this.DOMElement.style.top = DDElement.top + "px";
	this.DOMElement.style.left = DDElement.left + "px";
	// Check if there is a callback function to call
	if(DDElement.setupDragObject)
		DDElement.setupDragObject(this);
	// Make DragObject visible
	this.DOMElement.style.display = "block";
	// Calculate absolute position of DragObject
	this.calcPosition();
	// TODO	MediaCtlDropObject.recalcPositions();
}

DragObject.prototype.clearDragObject = function(){
	if(!this.DDElement) return;
	// Check if there is a callback function to call
	if(this.DDElement.clearDrapObject)
		this.DDElement.clearDrapObject(this);
	this.DOMElement.style.display = "none";
	this.DDElement = false;
	// Clear DropObject
	var DropObject = getDropObject();
	DropObject.clearDropObject();
}

DragObject.prototype.calcPosition = function(){
	var Element = this.DOMElement;
	this.left = 0;
	this.top  = 0;
	this.width = Element.offsetWidth;
	this.height = Element.offsetHeight;
	while (Element.offsetParent){
		this.left += Element.offsetLeft - Element.scrollLeft;
		this.top  += Element.offsetTop - Element.scrollTop;
		Element = Element.offsetParent;
	}
	this.left += Element.offsetLeft;
	this.top  += Element.offsetTop;
	this.bottom = this.top + this.height;
	this.right = this.left + this.width;
}

DragObject.prototype.stripIds = function(text){
	return text.replace(/id=\"([a-zA-Z0-9]*)\"/g, '');
}

DragObject.prototype.startDragging = function(ev){
	ev = ev || window.event;
	var mousePos = getMousePos(ev);
	// Calculate mouseOffset
	this.mouseOffsetX =	mousePos.left-this.left;
	this.mouseOffsetY =	mousePos.top-this.top;
	// Start dragging
	this.dragging = true;
	this.dragged = false;
}

DragObject.prototype.dragTo = function(ev){
	ev = ev || window.event;
	if(!this.dragging) return;
	if(!this.dragged){
		this.dragged = true;
		// Check if there is a callback function to call
		if(this.DDElement.startDragging)
			this.DDElement.startDragging(this);
	}
	var mousePos = getMousePos(ev);
	this.DOMElement.style.top = (mousePos.top-this.mouseOffsetY) + "px";
	this.DOMElement.style.left = (mousePos.left-this.mouseOffsetX) + "px";

	// Check if we moved over an dropable element
	this.DDElement.DraggableElementList.findActiveDropable(ev);
}

DragObject.prototype.stopDragging = function(){
	if(!this.dragging) return;
	// Check if element was dropped on something
	var DropObject = getDropObject();
	if(DropObject.DDElement){
		// Dropable Object found -> check if there is a callback function to call
		if(DropObject.DDElement.handleDrop){
			DropObject.DDElement.handleDrop(this.DDElement);
		}
	}
	// Stop dragging
	this.dragging = false;
	// TODO: what if mouse is still over the DDElement?
	if(this.dragged)
		this.clearDragObject();
}


function getDragObject(){
	if(!GlobalDragObject)
		GlobalDragObject = new DragObject();
	return GlobalDragObject;
}



/*
 *	=============================
 *    CLASS DropObject
 *	=============================
 */

function DropObject(){
	this.DDElement = false;
	// Create DOMElement
	var DOMElement = document.createElement('div');
	DOMElement.id = "DropObject";
	DOMElement.style.position = "absolute";
	//DOMElement.style.background = "green";
	//DOMElement.style.border="1px solid black";
	DOMElement.style.opacity = "0.7";
	DOMElement.style.display = "none";
	DOMElement.style.zIndex = "9998";
	document.getElementsByTagName('body')[0].appendChild(DOMElement);
	this.DOMElement = DOMElement;
	// Init position
	this.top = 0;
	this.left = 0;
	this.bottom = 0;
	this.right = 0;
	this.width = 0;
	this.height = 0;
}

DropObject.prototype.setupDropObject = function(DDElement){
	if(this.DDElement)
		this.clearDropObject();
	// Clone DDElement
	this.DDElement = DDElement;
	// remove all DOM ids to keep ids unique
	this.DOMElement.innerHTML = this.stripIds(DDElement.DOMElement.innerHTML);
	this.DOMElement.style.top = DDElement.top+"px";
	this.DOMElement.style.left = DDElement.left+"px";
	// Check if there is a callback function to call
	if(DDElement.setupDropObject)
		DDElement.setupDropObject(this);
	this.DOMElement.style.display = "block";
}

DropObject.prototype.clearDropObject = function(){
	if(!this.DDElement) return;
	// Check if there is a callback function to call
	if(this.DDElement.clearDropObject)
		this.DDElement.clearDropObject(this);
	this.DDElement = false;
	this.DOMElement.style.display = "NONE";
}

DropObject.prototype.stripIds = function(text){
	return text.replace(/id=\"([a-zA-Z0-9]*)\"/g, '');
}

function getDropObject(){
	if(!GlobalDropObject)
		GlobalDropObject = new DropObject();
	return GlobalDropObject;
}


/*
 *	=============================
 *    CLASS DragDropElement
 *	=============================
 */

function DragDropElement(element_id){
	this.DraggableElementList = false;
	this.element_name = false;
	this.element_type;
	// Setup DOMElement
	var DOMElement = document.getElementById(element_id);
	if(!DOMElement) alert('ELEMENT ' + element_id + ' not found'); //return; TODO REMOVE
	this.DOMElement = DOMElement;
	this.DOMCoverElement = false;
	// Add this element to list of DragDrop Elements
	DragDropElements[element_id] = this;
	// Init position
	this.top = 0;
	this.left = 0;
	this.bottom = 0;
	this.right = 0;
	this.width = 0;
	this.height = 0;
	// Init callback functions for DragElement
	this.setupDragObject = false; // function(DragObject)
	this.startDragging = false; // function(DragObject);
	this.clearDragObject = false; // function(DragObject)
	// Init callback function for DropElement
	this.setupDropObject = false; // function(DropObject)
	this.clearDropObject = false; // function(DropObject)
	this.handleDrop = false;  // function(DragObject)
	this.handleClick = false; // function()

	// Add event handlers
	this.DOMElement.onclick = function(ev){
		ev = ev || window.event;
		var DDElement = DragDropElements[this.id];
		if(DDElement.handleClick)
			DDElement.handleClick();
	}

	this.DOMElement.ondblclick = function(ev){
		ev = ev || window.event;
		// TODO: check why this doesn't work
		if(this.handleDblClick)
			this.handleDblClick();
	}

	// Calculate current position
	this.calcPosition();
}

DragDropElement.prototype.calcPosition = function(){
	var Element = this.DOMElement;
	this.left = 0;
	this.top  = 0;
	this.width = Element.offsetWidth;
	this.height = Element.offsetHeight;

	var offsetLeft;
	var offsetTop;

	while (Element.offsetParent){
		offsetTop = Element.offsetTop;
		offsetLeft = Element.offsetLeft;

		if(offsetTop<0){
			// IE BUG
			offsetTop = (Element.offsetParent.offsetHeight+offsetTop)-Element.offsetHeight;
		}
		if(offsetLeft<0){
			// IE BUG
			offsetLeft = (Element.offsetParent.offsetWidth+offsetLeft)-Element.offsetWidth;
		}
		//this.left += Element.offsetLeft - Element.scrollLeft;
		// Element.offsetTop - Element.scrollTop;

		this.left += offsetLeft;
		this.top  += offsetTop;
		Element = Element.offsetParent;
	}

	this.left += Element.offsetLeft;
	this.top  += Element.offsetTop;
	this.bottom = this.top + this.height;
	this.right = this.left + this.width;
}

DragDropElement.prototype.makeDraggable = function(DraggableElementList){
	this.DraggableElementList = DraggableElementList;
	// Cover the entire element with another div to prevent text selects
	this.DOMElement.innerHTML = this.DOMElement.innerHTML
		+ "<div id='" + this.DOMElement.id + "COVERDIV' style='position:absolute;top:0;left:0;width:100%;height:100%;opacity:0.3;'></div>";
	this.DOMCoverElement = document.getElementById(this.DOMElement.id + "COVERDIV");

	// Show onmouseover effect
	this.DOMElement.onmouseover = function(ev){
		ev = ev || window.event;
		// Don't do anything if there is already an active DragObject
		var DragObject = getDragObject();
		if(DragObject.dragging) return;
		// Highlight onmouseover
		DDElement = DragDropElements[this.id];
		var DragObject = getDragObject()
		DragObject.setupDragObject(DDElement);
	}

}

DragDropElement.prototype.highlightDraggable = function(){
	if(this.highlightDraggableCallback)
		this.highlightDraggableCallback(this,this);
}

DragDropElement.prototype.makeDropable = function(){

}


/*
 *	=============================
 *    CLASS DraggableElementList
 *	=============================
 */

function DraggableElementList(){
	this.ElementList = new Array();
	this.DropableElementMatrix = false;
}

DraggableElementList.prototype.addElement = function(DDElement){
	// Make DDElement draggable
	DDElement.makeDraggable(this);
	// Add DDElement to ElementList
	this.ElementList[this.ElementList.length] = DDElement;
}

DraggableElementList.prototype.setDropableElements = function(DropableElementList){
	this.DropableElementMatrix = new Array(DropableElementList);
}

DraggableElementList.prototype.appendDropableElements = function(DropableElementList){
	this.DropableElementMatrix[this.DropableElementMatrix.length] = DropableElementList;
}

DraggableElementList.prototype.findActiveDropable = function(ev){
	ev = ev || window.event;
	var mousePos = getMousePos(ev);
	var DropableElement = false;
	var DropObject = getDropObject();
	if(this.DropableElementMatrix){
		for(var i=0;i<this.DropableElementMatrix.length;i++){
			for(var j=0;j<this.DropableElementMatrix[i].ElementList.length;j++){
				DropableElement = this.DropableElementMatrix[i].ElementList[j];
				// Check what can be used as drop target
				// DropableElement.DOMElement.style.border = "1px solid black";
				if(
					DropableElement.top<mousePos.top && DropableElement.bottom>mousePos.top &&
					DropableElement.left<mousePos.left && DropableElement.right>mousePos.left
				){
					// Active element found
					DropObject.setupDropObject(DropableElement);
					return;
				}
			}
		}
	}

	// No active drop object found
	DropObject.clearDropObject();
}

/*
 *	=============================
 *    CLASS DropableElementList
 *	=============================
 */

function DropableElementList(){
	this.ElementList = new Array();
}

DropableElementList.prototype.reset = function(){
	this.ElementList = new Array();
}

DropableElementList.prototype.addElement = function(DDElement){
	// Make DDElement dropable
	DDElement.makeDropable();
	// Add DDElement to ElementList
	this.ElementList[this.ElementList.length] = DDElement;
}

/*
 *	=============================
 *   	MOUSE EVENTS
 *	=============================
 */
/**/
function getMousePos(ev){
	if(ev.pageX || ev.pageY){
		return {left:ev.pageX, top:ev.pageY};
	}
	return {
		left:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
		top:ev.clientY + document.body.scrollTop  - document.body.clientTop
	};
}

function mouseMove(ev){
	ev = ev || window.event;
	mousePos = getMousePos(ev);
	if(!document.getElementsByTagName('body')[0]) return;
	var DragObject = getDragObject();
	DragObject.dragTo(ev);
	return false;
}

function mouseUp(ev){
	//ev = ev || window.event;
	if(!document.getElementsByTagName('body')[0]) return;
	var DragObject = getDragObject();
	DragObject.stopDragging();
}

function initDragDrop(){
	var body = document.getElementsByTagName('body')[0];
	if(!body){
		setTimeout('initDragDrop()', 100);
		return;
	}
	document.onmousemove = mouseMove;
	document.onmouseup = mouseUp;
}

onload=initDragDrop;

// TODO: REMOVE
function loga(action){
	var a = document.getElementById('ta');
	if(a)
		a.innerHTML = action + "\n" + a.innerHTML;
}
