/**
 * var dl = new DragLayer().setProperties({
 *     contentId : "dayTermDescription",
 *     enableShadeButton : false,
 *     enableCloseButton : false,
 *     posX : document.body.clientWidth / 2 + 198,
 *     posY : 450//,
 * }).addOnloadListener();
 */

/**
 * 
 */
function DragLayer (contentId, status, posX, posY) {
	// proparty
	this.contentId = contentId  || '';
	this.status  = status || 'visible';
	this.posX    = posX   || 0;
	this.posY    = posY   || 0;
	this.baseLayerId = null;
	this.hasWrappingLayer = false;
	this.width = null;
	this.height = null;
	this.onMouseDragHandler = null;
	this.onMouseUpHandler = null;
	this.onMouseMoveHandler = null;
	this.onDoubleClickHandler = null;
	this.enableDrag = true;

	this.hasDragBound = true;

	// field
	this.content;
	this.dragElement;//
	this.eX;
	this.eY;
	this.baseLayer;
}

DragLayer.windowList = new Array();

DragLayer.maxZIndex = 0;

DragLayer.initialize = function () {
	// 「このファイルがあるフォルダ/拡張子なしファイル名」を取得
	// このフォルダ以下にCSSや画像ファイルを置く
	var baseFolder = CommonBase.getBaseFolder() + "/DragLayer";
	DragLayer.getBaseFolder = function () {
		return baseFolder;
	};
};
DragLayer.initialize();

DragLayer.prototype.setProperties = function (props) {
	for (var key in props) {
		if (typeof this[key] != "undefined") this[key] = props[key];
		else throw new Error("invalid property [" + key + "]");
	}
	return this;
};

DragLayer.prototype.setContent = function (content) {
	if (this.dragElement) {
		this.dragElement.width = "0";
		this.dragElement.replaceChild(content, this.content);
		this.dragElement.width = this.dragElement.clientWidth;
		this.content = content;
	} else {
		this.content = content;
		return this;
	}
};

DragLayer.prototype.addContent = function (content) {
	if (this.dragElement) {
		this.dragElement.width = "0";
		this.dragElement.appendChild(content);
		this.dragElement.width = this.dragElement.clientWidth;
	}
};

DragLayer.prototype.removeContent = function (content) {
	if (this.dragElement) {
		this.dragElement.width = "";
		this.dragElement.removeChild(content);
		this.dragElement.width = this.dragElement.clientWidth;
	}
};

DragLayer.prototype.setContentId = function (contentId) {
	if (this.dragElement) {
		this.contentId = contentId;
		this.setContent(document.getElementById(contentId));
	} else {
		this.contentId = contentId;
		return this;
	}
};

DragLayer.prototype.moveTo = function (posX, posY) {
	this.style.left = posX + "px";
	this.style.top = posY + "px";
//console.log(this.style.top + ":" + this.style.left);
};

DragLayer.prototype.moveBy = function (posX, posY) {
	this.style.left = (parseInt(this.style.left) + posX) + "px";
	this.style.top = (parseInt(this.style.top) + posY) + "px";
};

DragLayer.prototype.create = function () {
	if (! this.content) this.content = document.getElementById(this.contentId);
	if (this.hasWrappingLayer) {
		this.createWindow();
		this.dragElement.appendChild(this.content);
	} else {
		this.dragElement = this.content;
		if (this.baseLayerId) {
			this.baseLayer = document.getElementById(this.baseLayerId);
			if (this.baseLayer) this.baseLayer.appendChild(this.dragElement);
		}
	}
	this.style = this.dragElement.style;

	this.style.position = "absolute";

	this.style.left = this.posX + "px";
	this.style.top  = this.posY + "px";
	this.content.style.visibility = this.status;
	this.style.visibility = this.status;
	this.content.style.display = "block";
	this.style.display = "block";

//console.log(this.style.top + ":" + this.style.left);


	if (this.hasDragBound) {
		var parent = this.dragElement.parentNode;
		var size = this.getDlagElementSize();
		var parentSize = DragLayer.getElementSize(parent);
		this.limitX = parentSize[0] - size[0];
		this.limitY = parentSize[1] - size[1];
//console.log(parent.innerWidth + ":" + parent.scrollWidth + ":" + parent.offsetWidth + ":" + size);
		this.mouseMove = this.limitMouseMove;
	}

	this.setEventHandler();

	return this;
};

DragLayer.prototype.createWindow = function () {
	var dragElement = document.createElement("DIV");

//	dragElement.className = this.styles.defaultWindow;
	if (this.width)  dragElement.style.width  = this.width  + "px";
	if (this.height) dragElement.style.height = this.height + "px";
	dragElement.style.border  = "0";
	dragElement.style.margin  = "0";
	dragElement.style.padding = "0";

	this.dragElement = dragElement;
	if (this.baseLayerId) {
		this.baseLayer = document.getElementById(this.baseLayerId);
		if (this.baseLayer) this.baseLayer.appendChild(dragElement);
	} else {
		document.body.appendChild(dragElement);
	}
	return this;
};

DragLayer.prototype.setEventHandler = function () {
	var that = this;
	var dragElement = this.dragElement;
	// 発火間隔が短いので変数に
	var onMouseMoveHandler = this.onMouseMoveHandler;
	var onMouseDragHandler = this.onMouseDragHandler;

	var offsetPosition = this.getOffsetPosition(dragElement.offsetParent);

	if (! this.enableDrag) return this;
	var isMouseDown = false;
	var isMouseMove = false;


	/**
	 * 要素をドラッグするためのイベント
	 */
	Event.observe(dragElement, 'mousedown', function (evt) {
		isMouseDown = true;
		that.mouseDown(evt, dragElement);
//console.log("element.mousedown: " + that.limitX + " - " + that.limitY);
		Event.stop(evt);
	}, false);
	Event.observe(document, 'mousemove', function (evt) {
		if (isMouseDown) {
			that.mouseMove(evt, dragElement);
			isMouseMove = true;
			if (onMouseDragHandler) onMouseDragHandler(dragElement.offsetLeft, dragElement.offsetTop);
		}
//console.log("document.mousemove: " + isMouseDown + " - " + isMouseMove);
		return false;
	}, false);
	Event.observe(document, 'mouseup', function (evt) {
		if (isMouseDown) {
			isMouseDown = false;
			isMouseMove = false;
		}
	}, false);
	/**
	 * ベースレイヤーの位置を再計算
	 */
	Event.observe(dragElement, 'mouseover', function (evt) {
		if (that.enableDrag) {
			that.style.cursor = "move";
		} else {
			that.style.cursor = "auto";
		}
		offsetPosition = that.getOffsetPosition(dragElement.offsetParent);
	}, false);
	/**
	 * マウスポインタの位置
	 */
	Event.observe(dragElement, 'mousemove', function (evt) {
		if (isMouseDown) return;
		var position = that.mousePosition(evt, dragElement, offsetPosition);
		if (onMouseMoveHandler) onMouseMoveHandler(position[0], position[1]);
	}, false);
	/**
	 * マウスポインタの位置
	 */
	Event.observe(dragElement, 'dblclick', function (evt) {
		var position = that.mousePosition(evt, dragElement, offsetPosition);
		if (that.onDoubleClickHandler) that.onDoubleClickHandler(position[0], position[1]);
	}, false);
	return this;
};

// フローティングレイヤー内のマウスの位置
DragLayer.prototype.mousePosition = function (evt, layer, offset) {
	var eX  = Event.pointerX(evt);//evt.pageX || evt.clientX;
	var eY  = Event.pointerY(evt);//evt.pageY || evt.clientY;
	eX -= layer.offsetLeft + offset[0];
	eY -= layer.offsetTop  + offset[1];
	return [eX, eY];
}

// 最初にクリックした位置を記録します。
DragLayer.prototype.mouseDown = function (evt, target) {
	target.eX  = Event.pointerX(evt);//evt.pageX || evt.clientX;
	target.eY  = Event.pointerY(evt);//evt.pageY || evt.clientY;
	target.posX = parseInt(target.style.left);
	target.posY = parseInt(target.style.top);
};

DragLayer.prototype.mouseMove = function (evt, target) {
	if (!this.enableDrag) return;
	var eX  = Event.pointerX(evt);//evt.pageX || evt.clientX;
	var eY  = Event.pointerY(evt);//evt.pageY || evt.clientY;
	var posX = target.posX + (eX - target.eX);
	var posY = target.posY + (eY - target.eY);

	target.style.left = posX + "px";
	target.style.top  = posY + "px";
};

DragLayer.prototype.limitMouseMove = function (evt, target) {
	if (!this.enableDrag) return;
	var eX  = Event.pointerX(evt);//evt.pageX || evt.clientX;
	var eY  = Event.pointerY(evt);//evt.pageY || evt.clientY;
	var posX = target.posX + (eX - target.eX);
	var posY = target.posY + (eY - target.eY);

	if (posX > 0) posX = 0;
	else if (posX < this.limitX) posX = this.limitX;
	if (posY > 0) posY = 0;
	else if (posY < this.limitY) posY = this.limitY;

	target.style.left = posX + "px";
	target.style.top  = posY + "px";
//console.log(
//	"limitMouseMove: " + target.style.left + " : " + target.style.top
//	 + " : " + target.offsetLeft + " : " + target.offsetTop
//	 + " : " + target.eX + " : " + target.eY
//);
};

DragLayer.prototype.addOnloadListener = function () {
	var that = this;
	var listener = function () {
		that.create();
		Event.stopObserving(window, 'load', listener, false);
	};
	Event.observe(window, 'load', listener, false);
	return this;
};

// ブラウザのクライアント領域に対するドラッグ要素の位置
DragLayer.prototype.getOffsetPosition = function (node) {
	var offsetLeft = 0;
	var offsetTop = 0;
	if (node.offsetParent) {
		for (var n = node; n; n = n.offsetParent) {
			var x = n.offsetLeft;
			var y = n.offsetTop;
			if (! isNaN(x)) offsetLeft += x;
			if (! isNaN(y)) offsetTop  += y;
		}
	} else {
		offsetLeft = node.offsetLeft;
		offsetTop  = node.offsetTop;
	}
	return [offsetLeft, offsetTop];
}

DragLayer.prototype.getDlagElementSize = function () {
	var width  = 0;
	var height = 0;
	var size   = [0, 0];
	if (this.dragElement.clientWidth) {
		width  = this.dragElement.clientWidth;
		height = this.dragElement.clientHeight;
		size = DragLayer.getElementSize(this.dragElement);
	} else {
		for (var node = this.dragElement.firstChild; node; node = node.nextSibling) {
			if (node.clientWidth  && width  < node.clientWidth)  width  = node.clientWidth;
			if (node.clientHeight && height < node.clientHeight) height = node.clientHeight;
			var tempSize = DragLayer.getElementSize(node);
			if (size[0] < tempSize[0]) size[0] = tempSize[0];
			if (size[1] < tempSize[1]) size[1] = tempSize[1];
		}
		this.style.width  = width  + "px";
		this.style.height = height + "px";
	}
//	return [width, height];
	return size;
};

DragLayer.getElementSize = function (element) {
	if (element.nodeType != 1) return [0, 0];
	if (!element.style) return [0, 0];
	var els = element.style;

//console.log("nodeType:" + element.clientWidth + ":" + els.width);

//    if (els.display != 'none' && els.display != null) {// Safari bug
//      return [element.offsetWidth, element.offsetHeight];
//    }

	var originalVisibility = els.visibility;
	var originalPosition   = els.position;
	var originalDisplay    = els.display;
	els.visibility = 'hidden';
	els.position   = 'absolute';
	els.display    = 'block';
	var originalWidth  = element.clientWidth  || element.offsetWidth;
	var originalHeight = element.clientHeight || element.offsetHeight;
	els.display    = originalDisplay;
	els.position   = originalPosition;
	els.visibility = originalVisibility;
	return [originalWidth, originalHeight];
//      return [element.clientWidth, element.clientHeight];
};
