/******************************************************
 *
 * This script was written for
 * http://other.lookstrike.com
 *
 * If you plan to use it for your own, you can but you
 * MUST leave this whole comment intact in each file.
 *
 * Copyright		: (C) Jean-Sébastien Goupil - 2006-2008
 * Website		: http://other.lookstrike.com
 *
 ******************************************************/

var staticDynamicDrag;
var staticTimeoutId;
var staticArrayDynamicDragId = new Array();
var staticArrayDynamicDragCl = new Array();

function SetTimeoutDynamicDrag() {
	staticDynamicDrag.returnToStartGo();
}

function DynamicDrag(strId, strImg) {
	this.init(strId, strImg);
}

// We always drag the number 1
// The number 2 is there only for a trace.
DynamicDrag.prototype = {
	init: function(strId, strImg) {
		// Clear timeout if it was existing
		window.clearTimeout(staticTimeoutId);

		// Find Span & Create new one
		if(typeof(strId) == 'string')
			this.objSpan1 = document.getElementById(strId);
		else
			this.objSpan1 = strId;
		if(this.objSpan1 == null) {
			throw "[DRAG] Id Object1 is wrong";
		}
		// Set Style value
		this.objSpan1.style.position = "absolute";
		this.objSpan1.style.left = this.objSpan1.offsetLeft + "px";
		this.objSpan1.style.top = this.objSpan1.offsetTop + "px";

		// Watch out, don't clone if there is an image inside...
		// Since IE will ask for a new image to the server.
		if(strImg != null) {
			this.objSpan2 = this.objSpan1.cloneNode(false);
		} else {
			this.objSpan2 = this.objSpan1.cloneNode(true);
		}
		this.objSpan2.id = this.objSpan2.id + "_trace";
		this.objSpan1.parentNode.appendChild(this.objSpan2);

		// Create Images
		if(strImg != null) {
			this.img1 = document.createElement("img");
			this.img1.src = strImg;
			this.objSpan1.appendChild(this.img1);
			this.img2 = document.createElement("img");
			this.img2.src = strImg;
			this.objSpan2.appendChild(this.img2);
		}

		// Associate Images with span
		this.objSpan2.style.visibility = "hidden"; // Hide Trace

		this.nTransparent = 100;

		// zIndex
		this.objSpan1.style.zIndex = 2; // Trace
		this.objSpan2.style.zIndex = 1; // Drag Icon

		var nIndex = staticArrayDynamicDragId.length; // Future Reference
		staticArrayDynamicDragId[nIndex] = this.objSpan1.id;
		staticArrayDynamicDragCl[nIndex] = this;

		this.strGroup = ""; // Group for DragNDrop

		// Opacity
		this.bTransparentWhileReturn = false;

		// Return to Start
		this.bReturnToStart = false;
		this.nReturnX = 0;
		this.nReturnY = 0;
		this.fRealX = 0.0;
		this.fRealY = 0.0;
		this.fStepX = 0.0;
		this.fStepY = 0.0;
		this.nRapidity = 0;
		this.nPoints = 0;

		// Trace
		this.bLeaveTrace = false;

		// Callback
		this.callbackFunction = null
		this.callbackStatus = 0;

		this.fDragging = false;
		this.fReturning = false;

		this.objSpan1.style.cursor = "move";

		var events = ToolBox.events();

		events.register(this.objSpan1, "mousedown", this.beginDrag, true);
	},

	zIndexBase: function( nZindexBase ) {
		this.objSpan1.style.zIndex = nZindexBase + 2;
		this.objSpan2.style.zIndex = nZindexBase + 1;
	},

	leaveTrace: function( bLeaveTrace ) {
		this.bLeaveTrace = bLeaveTrace;
	},

	returnToStart: function( bReturnToStart, nRapidity, nPoints ) {
		this.bReturnToStart = bReturnToStart;
		this.nRapidity = parseInt(nRapidity);
		this.nPoints = parseInt(nPoints);
		this.fStepX = 0;
		this.fStepY = 0;
		this.returnX = parseInt(this.objSpan1.offsetLeft);
		this.returnY = parseInt(this.objSpan1.offsetTop);
	},

	setTransparent: function( nTransparent, bTransparentWhileReturn ) {
		this.nTransparent = parseInt(nTransparent);
		this.bTransparentWhileReturn = bTransparentWhileReturn;
	},

	setGroup: function(strGroup) {
		this.strGroup = strGroup;
	},

	beginDrag: function(event) {
		var events = ToolBox.events();
		var realEvent = events.get(event);

		// WOW opera has strange behavior... it doesn't use beginDrag and step directly to moveHandler !?
		if(ToolBox.specific().GetMouseClick(realEvent) != ToolBox.specific().MOUSE_LEFT) {
			return;
		}

		var tempStatic = staticArrayDynamicDragCl[ToolBox.findInArray(staticArrayDynamicDragId, this.id)];
		if(staticDynamicDrag == null || tempStatic == staticDynamicDrag) { // Prevent calling from another dynamic object
			staticDynamicDrag = tempStatic;
			if(staticDynamicDrag.fDragging == false) { // Can't start dragging if we are currently dragging (prevent bug when going out the viewport)
				var obj1 = staticDynamicDrag.objSpan1;
				var obj2 = staticDynamicDrag.objSpan2;
				// Does the image is currently returning ?
				if(staticDynamicDrag.fReturning == false) {
					// Do we leave a trace ?
					if(staticDynamicDrag.bLeaveTrace == true) {
						obj2.style.visibility = "visible";
						obj2.style.left = obj1.offsetLeft + "px";
						obj2.style.top = obj1.offsetTop + "px";
					} else {
						obj2.style.visibility = "hidden";
					}
				}

				// Move
				var x = parseInt(obj1.style.left);
				var y = parseInt(obj1.style.top);

				var deltaX = realEvent.clientX - x;
				var deltaY = realEvent.clientY - y;

				staticDynamicDrag.fDragging = true;
				ToolBox.specific().SetTransparency(obj1, staticDynamicDrag.nTransparent);

				// Register on document, not on object
				events.register(document, "mousemove", moveHandler, true);
				events.register(document, "mouseup", upHandler, true);

				oDynamicGroup.startDrag(staticDynamicDrag); // indicate we are dragging

				// Prevent Bubbling
				events.stopPropagation( realEvent );
				// Cancel method
				events.preventDefault( realEvent );

				if(staticDynamicDrag.callbackFunction != null) {
					staticDynamicDrag.callbackStatus = 1;
					staticDynamicDrag.callbackFunction(staticDynamicDrag);
				}
			}
		}

		function moveHandler(event) {
			var events = ToolBox.events();
			var realEvent = events.get(event);

			obj1.style.left = (realEvent.clientX - deltaX) + "px";
			obj1.style.top = (realEvent.clientY - deltaY) + "px";

			// Prevent Bubbling
			events.stopPropagation(realEvent);
			events.preventDefault(realEvent); // For IE and images

			if(staticDynamicDrag.callbackFunction != null) {
				staticDynamicDrag.callbackStatus = 2;
				staticDynamicDrag.callbackFunction(staticDynamicDrag);
			}
		}

		function upHandler(event) {
			staticDynamicDrag.fDragging = false; // We don't drag anymore
			if(staticDynamicDrag.bTransparentWhileReturn == false || staticDynamicDrag.bReturnToStart == false) {
				ToolBox.specific().SetTransparency(obj1, 100);
			}

			var events = ToolBox.events();
			var realEvent = events.get(event);
			// Unregister
			events.unregister(document, "mouseup", upHandler, true);
			events.unregister(document, "mousemove", moveHandler, true);

			// Prevent Bubbling
			events.stopPropagation( realEvent );

			if(staticDynamicDrag.callbackFunction != null) {
				staticDynamicDrag.callbackStatus = 3;
				staticDynamicDrag.callbackFunction(staticDynamicDrag);
			}

			oDynamicGroup.endDrag(); // We are finished

		}
	},

	GetGroup: function() {
		return this.strGroup;
	},

	DragAccepted: function(target) {
		this.checkReturnToStart();
	},

	DragRefused: function(target) {
		this.checkReturnToStart();
	},

	DragLost: function() {
		this.checkReturnToStart();
	},

	checkReturnToStart: function() {
		staticDynamicDrag = this;
		if(this.bReturnToStart == true) {
			this.temp = 0; // Counter
			this.realLeft = parseInt(this.objSpan1.style.left);
			this.realTop  = parseInt(this.objSpan1.style.top);
			this.fStepX = (this.returnX - this.realLeft) / this.nPoints;
			this.fStepY = (this.returnY - this.realTop ) / this.nPoints;
			this.returnToStartGo();
		} else {
			this.objSpan2.style.left = this.objSpan1.style.left;
			this.objSpan2.style.top = this.objSpan1.style.top
			this.objSpan2.style.visibility = "hidden";
			staticDynamicDrag = null;
		}
	},

	returnToStartGo: function() {
		if(this.fDragging == false) {
			this.fReturning = true;
			if(this.nRapidity == 0) {
				this.objSpan1.style.left = this.returnX + "px";
				this.objSpan1.style.top = this.returnY + "px";
			} else {
				this.realLeft += parseFloat(this.fStepX);
				this.realTop += parseFloat(this.fStepY);

				this.objSpan1.style.left = parseInt(this.realLeft) + "px";
				this.objSpan1.style.top = parseInt(this.realTop) + "px";
				if(++this.temp <= this.nPoints) {
					staticTimeoutId = window.setTimeout("SetTimeoutDynamicDrag()", (this.nRapidity / this.nPoints));
				} else {
					staticDynamicDrag = null;
					this.fReturning = false;
					this.objSpan1.style.left = this.returnX + "px";
					this.objSpan1.style.top = this.returnY + "px";
					this.objSpan2.style.visibility = "hidden";
					if(this.bTransparentWhileReturn == true) {
						ToolBox.specific().SetTransparency(this.objSpan1, 100);
					}
				}
			}
		}
	},

	SetCallback: function(callbackFunction) {
		this.callbackFunction = callbackFunction;
	},

	GetStatus: function() {
		return this.callbackStatus;
	}
}