/* DragManager class. Copyright by ADenis (adeniss@ukr.net) */

function DragManager(){	
	//New class variables

	this.object = null;
	this.dragger = null;
	this.sample = null;
	this.canvas = null;
	this.activeNode = null;
	this.className = "dragger";
	this.mouse = getMouse();
	this.dX = 0;
	this.dY = 0;
	this.x = "";
	this.y = "";
	this.onStop = null;
	this.onStopOver = null;
	this.onStopOut = null;
	this.onDrag = null;
	this.onDragOver = null;
	this.onDragOut = null;
	this.vDirection = "center";
	this.hDirection = "middle";
	this.showIbeam = false;
	
	this.start = function (object, canvas, showIbeam) {
		if (object.className)
		if (object.className.indexOf(this.className) > -1)
			return false;
		
		this.stop();
		
		this.object = object;
		this.dragger = this.object.cloneNode(true);
		
		if (canvas === undefined || canvas == null)
			this.canvas = null;
		else
			this.canvas = (canvas) ? canvas : this.object.parentNode;
		
		this.showIbeam = showIbeam;
		
		//this.canvas.style.border = "1px solid black";
		
		this.dragger.className = (this.dragger.className != "") ? (this.dragger.className + " " + this.className):this.className;
		
		if (this.showIbeam) {			
			this.sample = document.createElement("DIV");
			this.sample.className = "ibeam";
			document.body.appendChild(this.sample);			
		} else {
			this.sample = this.dragger.cloneNode(true);
		}

		var x = getX(this.object);
		var y = getY(this.object);
		this.x = x + "px";
		this.y = y + "px";
		this.dX = this.mouse.x - x;
		this.dY = this.mouse.y - y;

		this.sample.style.display = "none";		
		this.dragger.style.left = x + "px";
		this.dragger.style.top = y + "px";						
		this.dragger.style.position = "absolute";
		
		//this.canvas.insertBefore(this.dragger, this.canvas.firstChild);
		
		if (this.canvas) {
			this.canvas.insertBefore(this.dragger, this.canvas.firstChild);
		} else {
			document.body.appendChild(this.dragger);
			this.dragger.style.zIndex = 100;
		}        
		
		//this.drag();
		this.mouse.onMove = new Function("getDragManager().drag()");		
	}
	
	this.stop = function () {
		if (this.object) {
			
			// FF empty nodes workaround
			if (this.dragger)
			if (this.dragger.parentNode)
				this.dragger.parentNode.replaceChild(document.createElement("NOSCRIPT"), this.dragger);			
			delete this.dragger;			
			
			var isOverCanvas = false;
			
			if (this.canvas) {
				isOverCanvas = this.mouse.isOver(this.canvas);
			}
			
			if (this.sample.parentNode && this.sample.style.display != "none" && this.canvas) {
				if (this.showIbeam) {
					if (this.activeNode) {						
						if (this.hDirection == "right") {
							this.activeNode = this.getNextObjectNode(this.activeNode);
							
							if (this.activeNode) {
								this.canvas.insertBefore(this.object, this.activeNode);	
							} else {
								this.canvas.appendChild(this.object);
							}								
						} else {
							this.canvas.insertBefore(this.object, this.activeNode);
						}
					} else {
						this.canvas.appendChild(this.object);
					}
				} else {
					this.canvas.insertBefore(this.object, this.sample);
				}	
				
				if (isOverCanvas) {
					if (this.onStop) {
						this.onStop(this.object, this.activeNode, isOverCanvas);
						this.onStop = null;
					}
					
					if (this.onStopOver) {
						this.onStopOver(this.object, this.activeNode);
						this.onStopOver = null;					
					}					
				} else {
					if (this.onStop) {
						this.onStop(this.object, this.getActiveObject(), isOverCanvas);
						this.onStop = null;
					}
					
					if (this.onStopOut) {
						this.onStopOver(this.object, this.getActiveObject());
						this.onStopOver = null;					
					}					
				}
			} else {
                if (this.onStop) {
                    this.onStop(this.object, this.mouse.getActiveChild(document.body), false);
                    this.onStop = null;
                }
			}
			
			this.onDrag = null;
			
			if (this.sample)
			if (this.sample.parentNode)
				this.sample.parentNode.replaceChild(document.createElement("NOSCRIPT"), this.sample);
			delete this.sample;
		}
		
		this.object = null;
		this.dragger = null;
		this.sample = null;
		this.canvas = null;
		this.activeNode = null;
				
		this.mouse.onMove = null;		
	}
	
	this.drag = function() {			
		if (this.dragger && this.sample) {		
			var x = (this.mouse.x - this.dX) + "px";
			var y = (this.mouse.y - this.dY) + "px";
			
			var isDrag = false;
			
			if (this.x != x) {	
				this.dragger.style.left = x;
				this.x = x;
				isDrag = true;
			}
			
			if (this.y != y) {
				this.dragger.style.top = y;
				this.y = y;
				isDrag = true;
			}
			
			if (isDrag) {
				if (this.canvas && this.mouse.isOver(this.canvas)) {
					if (this.showIbeam) {
						this.positionIbeam(this.sample);
					} else {
						this.insertActiveNode(this.sample);
					}
					if (this.onDrag) {
						this.onDrag(this.object, this.activeNode, true);
					}
					
					if (this.onDragOver) {
						this.onDragOver(this.object, this.activeNode);
					}
				} else {
					if (this.onDrag) {
						this.onDrag(this.object, null, false);
					}
					
					if (this.onDragOut) {
						this.onDragOut(this.object, null);
					}
				}
			}
		}
	}
	
	this.positionIbeam = function(node) {
		var activeNode = this.getActiveNode(this.canvas);
		var needUpdate = (activeNode != this.activeNode);
		needUpdate = (needUpdate || (this.mouse.vDirection != this.vDirection));
		needUpdate = (needUpdate || (this.mouse.hDirection != this.hDirection));
		needUpdate = (needUpdate && activeNode);
		
		if (needUpdate) {
			if (this.mouse.hDirection == "left") {
				//before
				if (this.getPreviousObjectNode(activeNode) != this.object) {
					setAttribute(node.style, "display", "block");
					setAttribute(node.style, "left", getX(activeNode) - node.offsetWidth/2 + "px");
					setAttribute(node.style, "top", getY(activeNode) + (activeNode.offsetHeight - node.offsetHeight)/2 + "px");					
				} else {
					setAttribute(node.style, "display", "none");
				}
			} else if (this.mouse.hDirection == "right") {
				//after
				if (this.getNextObjectNode(activeNode) != this.object) {
					setAttribute(node.style, "display", "block");
					setAttribute(node.style, "left", getX(activeNode) - node.offsetWidth/2 + activeNode.offsetWidth + "px");
					setAttribute(node.style, "top", getY(activeNode) + (activeNode.offsetHeight - node.offsetHeight)/2 + "px");					
				} else {
					setAttribute(node.style, "display", "none");
				}			
			}
			
			this.activeNode = activeNode;			
			this.hDirection = this.mouse.hDirection;
			this.vDirection = this.mouse.vDirection;			
						
			return true;
		}	
		return false;
	}
	
	this.insertActiveNode = function(node) {
		var activeNode = this.getActiveNode(this.canvas);
		var needUpdate = (activeNode != this.activeNode);
		needUpdate = (needUpdate || (this.mouse.vDirection != this.vDirection));
		needUpdate = (needUpdate || (this.mouse.hDirection != this.hDirection));
		needUpdate = (needUpdate && activeNode);
				
		if (needUpdate){			
			if (this.mouse.vDirection == "top") {
				//before
				if (this.getPreviousObjectNode(activeNode) != this.object) {
					setAttribute(node.style, "display", this.object.style.display);
					this.canvas.insertBefore(node, activeNode);
				} else {
					setAttribute(node.style, "display", "none");
				}
			} else if (this.mouse.vDirection == "bottom") {
				//after
				if (activeNode.nextSibling) {
					if (this.getNextObjectNode(activeNode) != this.object) {
						setAttribute(node.style, "display", this.object.style.display);
						this.canvas.insertBefore(node, activeNode.nextSibling);
					} else {
						setAttribute(node.style, "display", "none");
					}
				} else {
					this.canvas.appendChild(node);
				}
			}
			
			this.activeNode = activeNode;
			this.vDirection = this.mouse.vDirection;
			this.hDirection = this.mouse.hDirection;
			
			return true;
		}		
		return false;
	}
	
	this.getPreviousObjectNode = function(object) {
		while (object = object.previousSibling) {
			if (object.tagName && object != this.sample && object != this.dragger && object != this.object) {
				return object;
			}
		}		
		return false;
	}
	
	this.getNextObjectNode = function(object) {
		while (object = object.nextSibling) {
			if (object.tagName && object != this.sample && object != this.dragger && object != this.object) {
				return object;
			}
		}		
		return false;
	}	

	this.getActiveNode = function(canvas) {
		if (this.dragger) {
			var childs = canvas.childNodes;
			var length = childs.length;
			
			for (var i = 0; i < length; i++) {			
				if (this.mouse.isOver(childs[i])) {
					if (childs[i] != this.dragger && childs[i] != this.object && childs[i] != this.sample)
						return childs[i];
				}
			}
		}
		return false;
	}
	
	this.getActiveObject = function() {
		return this.mouse.getActiveChild(document.body);
	}	
}

var dragManager = new DragManager();

function getDragManager() {
	if (!dragManager) {
		dragManager = new DragManager();
	}
	
	return dragManager;
}