/*

Generic drag drop class for moving stuff around

*/
function DragDrop(onEnd, onDrag, dragStyle){
	var that = this;
	
	this.onEnd = onEnd || function(){};
	this.onDrag = onDrag || function(){};
	this.dragStyle = dragStyle || {};
	
	// function to track mouse movement. Gets added/removed for each drag and needs a closure, so define it here
	this.mousemove = function(e){ that.onMouseMove(e); };
	this.mouseup = function(e){ that.endDrag(e); };
	
	// functions to stop text selection in IE- also added/removed for each drag
	this.killSelect = function(){ return false; };
	
};


/*
- dragElements: elements that can be dragged and dropped
*/
DragDrop.prototype.addElements = function(dragElements){
	var that = this,
			dragElements = this.processElementArgument(dragElements);
	

	// add drag event to each dragElement (or its drag handle if such a thing exists)
	for (var i = 0, il = dragElements.length; i < il; i++){
		base2.DOM.bind(dragElements[i]);
		
		dragElements[i].style.MozUserSelect = 'none';
		
		// get handle if one exists, otherwise use the element itself
		handle = dragElements[i].querySelector('.dragHandle') || dragElements[i];
		//console.log(handle);
		addEvent(handle, 'mousedown',
			(function(dragEl){
				return function(e){
					that.startDrag(dragEl, e);
				}
			})(dragElements[i])
		);
		
	}
		
};


//PRIVATE METHODS:

// begins a drag- li is the child elements to be dragged, e is the mousedown event
DragDrop.prototype.startDrag = function(element, e){
	//console.log(element);
	this.currentEl = element;
	
	// get mouse start position for figuring out relative mouse coords
	this.currentPos = [e.clientX - parseInt(element.style.left) || 0, e.clientY - parseInt(element.style.top) || 0];

	// aesthetics
	element.style.zIndex = 9999;
	for (var i in this.dragStyle)
		element.style[i] = this.dragStyle[i];
	
	// make/show overlay
	if (!this.overlay)
		this.createOverlay();
	else
		this.overlay.style.display = 'block';
	
	// prevent text selection
	document.body.focus();
	
	// kill text selection in IE
	addEvent(document.body, 'selectstart', this.killSelect);
	addEvent(document.body, 'drag', this.killSelect);
	
	// functions to move
	addEvent(document, 'mousemove', this.mousemove);
	addEvent(document, 'mouseup', this.mouseup);
};



// called when mouse is moved (only while a drag is in process) e is the mousemove event
DragDrop.prototype.onMouseMove = function(e){
	var pos = this.getRelativeMouseCoords(e);
	
	this.currentEl.style.left = pos[0] + 'px';
	this.currentEl.style.top = pos[1] + 'px';
	
	this.onDrag(this.currentEl);
};


// reverts everything back to normal once the drag has finished (triggered onmouseup)
DragDrop.prototype.endDrag = function(){
	document.onselectstart = null;
	removeEvent(document, 'mousemove', this.mousemove);
	removeEvent(document, 'mouseup', this.mouseup);
	removeEvent(document.body, 'selectstart', this.killSelect);
	removeEvent(document.body, 'drag', this.killSelect);
	
	// aesthetics
	this.currentEl.style.zIndex = '';
	this.currentEl.style.opacity = '';
	
	// remove overlay
	this.overlay.style.display = 'none';
	
	this.onEnd(this.currentEl);
	
};


// processes a function argument that can be a single element or an array of elements
// each element can be an actual reference or a string (id of an element)
// returns an array of element references
DragDrop.prototype.processElementArgument = function(el){
	// if el[0] is defined, assume that the argument is an array of elements; otherwise it must be a single element
	if(!el[0])
		el = [el];
	for (var i = 0, il = el.length; i < il; i++){
		if(typeof el[i] === 'string')
			el[i] = $(el[i]);
	}
	return el;
};

// creates an overlay to 'grey out' the document while dragging, and also to negate the effects of any iframes
DragDrop.prototype.createOverlay = function(e){
	this.overlay = document.body.appendChild(document.createElement('div'));
	var styles = {'position' : 'fixed', 'top' : '0px', 'left' : '0px', 'width' : '100%', 'height' : '100%', 'zIndex' : 999, 'background' : '#FFF', 'opacity' : 0};
	for (var i in styles)
		this.overlay.style[i] = styles[i];
};

// gets mouse coords relative to their previous position
DragDrop.prototype.getRelativeMouseCoords = function(e){
	return [e.clientX - this.currentPos[0], e.clientY - this.currentPos[1]];	
};

