// drag.js - Drag support for dynamic layers

// startup flag
var gMod_Drag = true;

// prerequisites
var gMod_Mouse;
if (!gMod_Mouse){alert("You must load mouse.js before drag.js");}
var gMod_Layer;
if (!gMod_Layer){alert("You must load layer.js before drag.js");}
var gMod_Window;
if (!gMod_Window){alert("You must load window.js before drag.js");}
var gMod_Move;
if (!gMod_Move){alert("You must load move.js before drag.js");}

/////////////////////////////////////////////////////////////////////////////////////////////

var gNextDragID = 1;

function Drag(name) {

	this.name = name;
	this.dragid = gNextDragID++;
	this.obj = null;
	this.array = new Array();
	this.dropTargets = new Array();
	this.active = false;
	this.offsetX = 0;
	this.offsetY = 0;
	this.zIndex = 0;
	this.constrain = true;
	this.resort = true;
	this.add = DragAdd;
	this.addTargets = DragAddTargets;
	this.checkTargets = DragCheckTargets;
	this.targetHit == null;
	this.remove = DragRemove;
	this.setGrab = DragSetGrab;
	this.mouseDown = DragMouseDown;
	this.mouseMove = DragMouseMove;
	this.mouseUp = DragMouseUp;
	this.onDragStart = new Function();
	this.onDragMove = new Function();
	this.onDragEnd = new Function();
	this.onDragDrop = new Function();

	if (name){
		mouse.addDown(name+".mouseDown");
		mouse.addMove(name+".mouseMove");
		mouse.addUp(name+".mouseUp");
	}
}

function DragAdd() {
	for (var i=0; i<arguments.length; i++) {
		var l = this.array.length;
		this.array[l] = arguments[i];
		this.array[l].dragGrab[this.dragid] = new Array(0,this.array[l].w,this.array[l].h,0);
		this.zIndex += 1;
	}
}
function DragAddTargets() {
	for (var i=0; i<arguments.length; i++) {
		var l = this.dropTargets.length
		this.dropTargets[l] = arguments[i]
		this.dropTargets[l].dragGrab[this.dragid] = new Array(0,this.dropTargets[l].w,this.dropTargets[l].h,0)
	}
}
function DragSetGrab(dynlayer,top,right,bottom,left){
	dynlayer.dragGrab[this.dragid] = new Array(top,right,bottom,left);
}
function DragRemove() {
	for (var i=0; i<arguments.length; i++) {
		for (var j=0; j<this.array.length; j++) {
			if (this.array[j]==arguments[i]) {
				for (var k=j;k<=this.array.length-2;k++) this.array[k] = this.array[k+1]
				this.array[this.array.length-1] = null
				this.array.length -= 1
				break
			}
		}
	}
}
function DragMouseDown(x,y) {
	for (var i=this.array.length-1;i>=0;i--) {
		var lyr = this.array[i];
		//alert('hit at '+x+','+y);
		//alert('layer at '+lyr.x+','+lyr.y);
		if (checkWithinLayer(x,y,lyr,this.dragid)) {
			this.obj = this.array[i];
			this.offsetX = x-this.obj.x;
			this.offsetY = y-this.obj.y;
			this.active = true;
			//alert('hit');
			break;
		}
	}
	if (!this.active){
		return false;
	}else{
		if (this.resort){
			this.obj.css.zIndex = this.zIndex++
			for (var j=i;j<=this.array.length-2;j++) this.array[j] = this.array[j+1]
			this.array[this.array.length-1] = this.obj
		}
		this.onDragStart(x,y)
		return true
	}
}

function DragMouseMove(x,y) {
	if (!this.active) return false;
	else {
		var MovX = x-this.offsetX;
		var MovY = y-this.offsetY;
		if (this.constrain){if (MovX<0){MovX=0;}}
		if (this.constrain){if (MovY<0){MovY=0;}}
		if (this.constrain){if (MovX>(winman.width()-this.obj.w)){MovX=(winman.width()-this.obj.w);}}
		if (this.constrain){if (MovY>(winman.height()-this.obj.h)){MovY=(winman.height()-this.obj.h);}}
		this.obj.moveTo(MovX,MovY);
		this.onDragMove(x,y);
		return true;
	}
}
function DragMouseUp(x,y) {
	if (!this.active) return false
	else {
		this.active = false
		if (this.checkTargets()) this.onDragDrop()
		this.onDragEnd(x,y)
		return true
	}
}
function DragCheckTargets() {
	for (i in this.dropTargets) {
		var lyr = this.dropTargets[this.dragid][i]
		if (checkWithinLayer(lyr.x,lyr.y,this.obj,this.dragid) ||
		checkWithinLayer(lyr.x+lyr.w,lyr.y,this.obj,this.dragid) ||
		checkWithinLayer(lyr.x,lyr.y+lyr.h,this.obj,this.dragid) ||
		checkWithinLayer(lyr.x+lyr.w,lyr.y+lyr.h,this.obj,this.dragid) ||
		checkWithinLayer(this.obj.x,this.obj.y,lyr,this.dragid) ||
		checkWithinLayer(this.obj.x+this.obj.w,this.obj.y,lyr,this.dragid) ||
		checkWithinLayer(this.obj.x,this.obj.y+this.obj.h,lyr,this.dragid) ||
		checkWithinLayer(this.obj.x+this.obj.w,this.obj.y+this.obj.h,lyr,this.dragid)) {
			this.targetHit = lyr
			return true
		}
	}
	return false
}

function checkWithin(x,y,left,right,top,bottom) {
	if (x>=left && x<right && y>=top && y<bottom) return true
	else return false
}
function checkWithinLayer(x,y,lyr,dragid) {
	if (checkWithin(x,y,lyr.x+lyr.dragGrab[dragid][3],lyr.x+lyr.dragGrab[dragid][1],lyr.y+lyr.dragGrab[dragid][0],lyr.y+lyr.dragGrab[dragid][2])) return true
	else return false
}

// automatically define the default "drag" Drag Object and link it into the mouse hook

drag = new Drag("drag");

/////////////////////////////////////////////////////////////////////////////////////////////
