function DragDrop(limit) {
	this.target = false;
	this.id = false;
	this.limit = limit;
	this.output = false;
	this.browser = this.getBrowser();
	this.motion = true; // モーション表示の選択
	this.clone = false;
	this.mouse = { x: false, y: false };
	this.offset = { x: false, y: false };

	// ゴミ箱
	this.trashBox = new TrashBox("tb0", "tools");
	this.trashBox.getTrashBox();

/*
	// for debug
	this.debug = new Debug("debug");
	var debugObj = {
		"_browser": this.browser,
		"_targetId": false,
		"_targetZ": false,
		"_cloneId": false,
		"_cloneZ": false,
		"_mouse": "(" + this.mouse.x + ", " + this.mouse.y + ")",
		"_offset": "(" + this.offset.x + ", " + this.offset.y + ")"
	};
	this.debug.setStatus(debugObj);
*/
}

// ブラウザの種類を取得
DragDrop.prototype.getBrowser = function() {
	var str = navigator.appName;
	// Netscape, Firefox, Safari
	if (str.match(/netscape/i)) { return "ns"; }
	// Internet Explorer
	else if (str.match(/explorer/i)) { return "ie"; }
	// Opera
	else if (str.match(/opera/i)) { return "op"; }
	else { return false; }
}

// ドラッグ対象を設定
DragDrop.prototype.setTarget = function(e, target, output) {
	if (this.target) { return false; }
	if (!this.browser) { return false; }
	this.target = target;
	this.output = output;
	this.id = target.getAttribute("id");
	this.setOffset(e);
	this.createClone();

	// for debug
	var debugObj = {
		"_targetId": this.target.getAttribute("id"),
		"_targetZ": this.target.style.zIndex,
		"_cloneId": this.clone.getAttribute("id"),
		"_cloneZ": this.clone.style.zIndex,
		"_offset": "(" + this.offset.x + ", " + this.offset.y + ")"
	};
	//this.debug.updateStatus(debugObj);
}

// クリックされたdiv要素を最前面へ移動
DragDrop.prototype.moveFront = function(target, output) {
	var z = { before: target.style.zIndex -0, after: false };
	var myLength = output.childNodes.length -0;
	target.style.zIndex = myLength;
	for (i = 0; i < myLength; i++) {
		z.after = output.childNodes[i].style.zIndex -0;
		if (z.after > z.before) {
			output.childNodes[i].style.zIndex = --z.after;
		}
	}
}

// マウス座標を設定する
DragDrop.prototype.setMouse = function(e) {
	if (!this.target) { return false; }
	if (!this.browser) { return false; }
	switch(this.browser) {
		case "ns":
			this.mouse.x = parseInt(e.pageX);
			this.mouse.y = parseInt(e.pageY);
			break;
		case "ie":
			this.mouse.x = parseInt(event.x);
			this.mouse.y = parseInt(event.y);
			break;
		case "op":
			this.mouse.x = parseInt(event.x);
			this.mouse.y = parseInt(event.y);
			break;
		default:
			break;
	}
}

// オフセット座標を設定する
DragDrop.prototype.setOffset = function(e) {
	if (!this.target) { return false; }
	if (!this.browser) { return false; }
	switch(this.browser) {
		case "ns":
			this.offset.x = parseInt(e.layerX) - 1; // 固定値
			this.offset.y = parseInt(e.layerY) - 1;
			break;
		case "ie":
			//var adjust = 2 + parseInt(this.target.style.border);
			this.offset.x = parseInt(event.offsetX) + 3; // 2 + border-width
			this.offset.y = parseInt(event.offsetY) + 3;
			break;
		case "op":
			this.offset.x = parseInt(event.offsetX) + 1; // border-width
			this.offset.y = parseInt(event.offsetY) + 1;
			break;
		default:
			break;
	}
}

DragDrop.prototype.createClone = function() {
	if (this.clone) { return false; }
	this.clone = this.target.cloneNode(true);
	this.clone.setAttribute("id", "clone");
	this.setOpacity(this.clone, 0.5);
	this.clone.style.zIndex = parseInt(this.target.style.zIndex) + 1;
	this.output.appendChild(this.clone);
}

DragDrop.prototype.dragTarget = function(e) {
	if (!this.target) { return false; }
	if (!this.browser) { return false; }
	this.setMouse(e);
	this.clone.style.left = this.mouse.x - this.offset.x + "px";
	this.clone.style.top = this.mouse.y - this.offset.y + "px";
	this.checkLimit(parseInt(this.clone.style.left), parseInt(this.clone.style.top));
	if (this.id != "form0") {
		this.trashBox.checkTrash(this.mouse.x, this.mouse.y);
	}

	// for debug
	var debugObj = {
		"_mouse": "(" + this.mouse.x + ", " + this.mouse.y + ")"
	};
	//this.debug.updateStatus(debugObj);
}

DragDrop.prototype.dropTarget = function() {
	if (!this.target) { return false; }
	if (!this.clone) { return false; }
	if (this.motion) { this.showMotion(); }
	else {
		this.target.style.left = this.clone.style.left;
		this.target.style.top = this.clone.style.top;
	}
	var cood = {
		x: parseInt(this.clone.style.left),
		y: parseInt(this.clone.style.top)
	};
	this.output.removeChild(this.clone);
	if (this.id == "form0") { this.setFormCoordinate(cood.x, cood.y); }
	this.resetProps();

	// for debug
	var debugObj = {
		"_browser": this.browser,
		"_targetId": this.target,
		"_targetZ": false,
		"_cloneId": this.clone,
		"_cloneZ": false,
		"_mouse": "(" + this.mouse.x + ", " + this.mouse.y + ")",
		"_offset": "(" + this.offset.x + ", " + this.offset.y + ")"
	};
	//this.debug.updateStatus(debugObj);
}

DragDrop.prototype.setFormCoordinate = function(x, y) {
	document.getElementById("x").value = x;
	document.getElementById("y").value = y;
}

DragDrop.prototype.resetProps = function() {
	this.target = false;
	this.clone = false;
	this.mouse = { x: false, y: false };
	this.offset = { x: false, y: false };
	this.limit.error = false;
}

// 透明度を設定する
// 引数は、オブジェクトIDと透明度（0～1）
DragDrop.prototype.setOpacity = function(target, value) {
	if (!this.browser) { return false; }
	switch(this.browser) {
		case "ns":
			target.style.MozOpacity = value;
			break;
		case "ie":
			var ieValue = "alpha(opacity=" + parseFloat(value) * 100 + ")";
			target.style.filter = ieValue;
			break;
		case "op":
			target.style.opacity = value;
			break;
		default:
			break;
	}
}

// ドロップ時にモーションを表示する
DragDrop.prototype.showMotion = function() {
	var divide = 15; // モーション分割数。奇数を設定する

	var start = {
		x: parseInt(this.target.style.left),
		y: parseInt(this.target.style.top)
	};
	var end = {
		x: parseInt(this.clone.style.left),
		y: parseInt(this.clone.style.top)
	};
	var d = {
		x: (start.x - end.x),
		y: (start.y - end.y)
	};

	var center = (divide + 1) / 2;
	var delta = new Array();
	for (i = 0; i < center; i++) {
		delta[i] = { x: Math.floor(d.x >> i), y: Math.floor(d.y >> i) };
	}

	var point = new Array();
	var shift = center - 1;
	for (i = 0; i < divide; i++) {
		if (i == 0) {
			point[i] = { x: start.x + "px", y: start.y + "px" }
		}
		else if (i < center -1) {
			point[i] = {
				x: start.x - delta[shift].x + "px",
				y: start.y - delta[shift].y + "px"
			};
			shift--;
		}
		else if (i >= center - 1 && i < divide - 1) {
			point[i] = {
				x: end.x + delta[shift].x + "px",
				y: end.y + delta[shift].y + "px"
			};
			shift++;
		}
		else if ( i == divide - 1)  {
			point[i] = { x: end.x + "px", y: end.y + "px" };
		}
	}

	// setIntervalスコープ内でthisを保持できないので
	// targetにthis.targetを代入しておく
	var target = this.target;
	var count = 0;
	var myTimer = setInterval(
		function() {
			if (count < divide - 1) {
				target.style.left = point[count].x;
				target.style.top = point[count].y;
				count++;
			}
			else if (count == divide - 1) {
				target.style.left = point[count].x;
				target.style.top = point[count].y;
				clearInterval(myTimer);
			}
			else {
				clearInterval(myTimer);
			}
		}, 10);
}

DragDrop.prototype.checkLimit = function(x, y) {
	if (x < this.limit.x.min || x > this.limit.x.max || y < this.limit.y.min || y > this.limit.y.max) {
		this.limit.error = true;
	}
	else { this.limit.error = false; }
}

DragDrop.prototype.undoMove = function() {
	var divide = 15; // モーション分割数。奇数を設定する

	var start = {
		x: parseInt(this.clone.style.left),
		y: parseInt(this.clone.style.top)
	};
	var end = {
		x: parseInt(this.target.style.left),
		y: parseInt(this.target.style.top)
	};
	var d = {
		x: (start.x - end.x),
		y: (start.y - end.y)
	};

	var center = (divide + 1) / 2;
	var delta = new Array();
	for (i = 0; i < center; i++) {
		delta[i] = { x: Math.floor(d.x >> i), y: Math.floor(d.y >> i) };
	}

	var point = new Array();
	var shift = center - 1;
	for (i = 0; i < divide; i++) {
		if (i == 0) {
			point[i] = { x: start.x + "px", y: start.y + "px" }
		}
		else if (i < center -1) {
			point[i] = {
				x: start.x - delta[shift].x + "px",
				y: start.y - delta[shift].y + "px"
			};
			shift--;
		}
		else if (i >= center - 1 && i < divide - 1) {
			point[i] = {
				x: end.x + delta[shift].x + "px",
				y: end.y + delta[shift].y + "px"
			};
			shift++;
		}
		else if ( i == divide - 1)  {
			point[i] = { x: end.x + "px", y: end.y + "px" };
		}
	}

	// setIntervalスコープ内でthisを保持できないので
	// cloneとoutputを変数に代入しておく
	var clone = this.clone;
	var output = this.output;
	var count = 0;
	var myTimer = setInterval(
		function() {
			if (count < divide - 1) {
				clone.style.left = point[count].x;
				clone.style.top = point[count].y;
				count++;
			}
			else if (count == divide - 1) {
				clone.style.left = point[count].x;
				clone.style.top = point[count].y;
				output.removeChild(clone);
				clearInterval(myTimer);
			}
			else {
				clearInterval(myTimer);
			}
		}, 10);
}
