Function.prototype.bind = function(object) {
    var __method = this;
    return function() {
        return __method.apply(object, arguments);
    }
}

function RectangleUnit() 
{
	this.initialize.apply(this, arguments);
}
RectangleUnit.prototype = 
{
	initialize: function(x, y, height, width) 
	{
		this.x = x;
		this.y = y;
		this.width = width;
		this.height = height;
	}
}

function PopupDiv() 
{
	this.initialize.apply(this, arguments);
}
PopupDiv.prototype = 
{
	initialize: function(x, y, width, height) 
	{
		this.x = x;
		this.y = y;
		this.width = width;
		this.height = height;
		this.unit =  new RectangleUnit('px', 'px', 'px', 'px');
		this.setFps(24);
		this.style = new Array();
		this.body = "";
		this.element = document.createElement("div"); 
		this.xType = "left";
		this.yType = "top";
	}
,
	setFps: function(fps)
	{
		this.fps = fps;
		this.interval = 1000 / fps;
	}
,
	setBody: function(text)
	{
		this.body = text;
		this.element.innerHTML = this.body;
	}
,
	setRectangle: function(x, y, width, height)
	{
		var s = this.element.style;
		if(this.xType == 'right')
		{
			s['left'] = (this.getWindowX() + this.getWindowWidth() - this.getWidth() - x ) + this.unit.x
		}
		else
			s[this.xType] = x + this.unit.x;

		if(this.yType == 'bottom')
		{
			s.top = (this.getWindowY() + this.getWindowHeight() - this.getHeight() - y) + this.unit.y
		}
		else
			s[this.yType] = y + this.unit.y;
		s.width = width + this.unit.width;
		s.height = height + this.unit.height;
	}
,
	setup: function(x, y, width, height)
	{
		//スタイルをセットし、htmlに送る
		
		for(var index in this.style)
		{
			this.element.style[index] = this.style[index];
		}
		this.element.style.position = "absolute";
		this.setRectangle(x, y, width, height)
		
		this.element.innerHTML = this.body;
		document.body.appendChild(this.element);
	}
,
	close: function()
	{
		document.body.removeChild(this.element);
		
	}
,
	show: function() 
	{
		this.setup(this.x, this.y, this.width, this.height);
	}
,
	moveFrom: function(x, y, width, height, speed)
	{
		//x, yから元の位置に移動する
		
		//移動量を割り出す
		var sec = speed / this.interval;
		this.moveX = (this.x - x) / sec;
		this.moveY = (this.y - y) / sec;
		this.moveWidth = (this.width - width) / sec;
		this.moveHeight = (this.height - height) / sec;

		this.setup(x, y, width, height);
		this.nowX = x;
		this.nowY = y;
		this.nowWidth = width;
		this.nowHeight = height;
		this.timer = setTimeout(this.updateMove.bind(this), this.interval);
	}

,
	updateMove: function()
	{
		var ba = this.updateMoveX();
		var bb = this.updateMoveY();
		var bc = this.updateMoveWidth();
		var bd = this.updateMoveHeight();
		if(ba || bb || bc || bd)
		{
			this.setRectangle(this.nowX, this.nowY, this.nowWidth, this.nowHeight);
			this.timer = setTimeout(this.updateMove.bind(this), this.interval);
		}
		else
		{
			this.setRectangle(this.x, this.y, this.width, this.height);
			if(this.onFinishMove != undefined) this.onFinishMove();
		}
	}
,
	getMovedValue: function(from, to, plus)
	{
		//fromにplusを足し、toを越えたらtoを返す
		var isDown = (to < from);
		from += plus;
		return (this.x == from || (isDown != (to < from)))? to: from;
	}
,
	updateMoveX: function()
	{
		this.nowX = this.getMovedValue(this.nowX, this.x, this.moveX);
		return (this.nowX != this.x);
	}
,
	updateMoveY: function()
	{
		this.nowY = this.getMovedValue(this.nowY, this.y, this.moveY);
		return (this.nowY != this.y);
	}
,
	updateMoveWidth: function()
	{
		this.nowWidth = this.getMovedValue(this.nowWidth, this.width, this.moveWidth);
		return (this.nowWidth != this.width);
	}
,
	updateMoveHeight: function()
	{
		this.nowHeight = this.getMovedValue(this.nowHeight, this.height, this.moveHeight);
		return (this.nowHeight != this.height);
	}
,
	getLeft: function (){
	 	var div = this.element;
		return document.layers?div.left:(div.offsetLeft||div.style.pixelLeft||0);
	}
,
	getTop: function (){
	 	var div = this.element;
	   return document.layers?div.top:(div.offsetTop||div.style.pixelTop||0);
	}
,
	getWidth: function  (){ 
	 	var div = this.element;
	  return document.layers?
	         div.clip.width:(div.offsetWidth||div.style.pixelWidth||0);
	}
,
	getHeight: function (){
	 	var div = this.element;
	  return document.layers?
	         div.clip.height:(div.offsetHeight||div.style.pixelHeight||0);
	}
,
	getWindowHeight: function (){
	  if(window.innerHeight) return window.innerHeight; // Mozilla, Opera, NN4
	  if(document.documentElement && document.documentElement.clientHeight){ // 以下 IE
	   return document.documentElement.clientHeight;
	  }
	  else if(document.body && document.body.clientHeight){
	   return document.body.clientHeight;
	  }
	  return 0;
	}
,
	getWindowWidth: function (){
	  if(window.innerWidth) return window.innerWidth; // Mozilla, Opera, NN4
	  if(document.documentElement && document.documentElement.clientWidth){ // 以下 IE
	   return document.documentElement.clientWidth;
	  }
	  else if(document.body && document.body.clientWidth){
	   return document.body.clientWidth;
	  }
	  return 0;
	}
,
	getWindowX: function()
	{
		if(window.scrollX) return window.scrollX; // Moziila
		if(window.pageXOffset) return window.pageXOffset; // Opera, NN4
		if(document.documentElement && document.documentElement.scrollLeft)
		{ // 以下 IE
			return document.documentElement.scrollLeft;
		}
  		else if(document.body && document.body.scrollLeft)
  		{
   			return document.body.scrollLeft;
  		}
  		return 0;
	}
,
	getWindowY: function()
	{
		if(window.scrollY) return window.scrollY; // Mozilla
		if(window.pageYOffset) return window.pageYOffset; // Opera, NN4
		if(document.documentElement && document.documentElement.scrollTop)
		{ // 以下 IE
			return document.documentElement.scrollTop;
		}
		else if(document.body && document.body.scrollTop)
		{
			return document.body.scrollTop;
		}
		return 0;
	}		
};

function WindowButtonDiv(x, y, w, h)
{
	var self = new PopupDiv(x, y, w, h);
	self.window = undefined;
	self.element.onclick = function()
	{
		if(self.window == undefined)
		{
			self.window = self.openWindow();
		}
	};
	self.openWindow = function()
	{
		var win = this.getWindow();
		this.setupWindow(win);
		this.showWindow(win);
		return win;
	};
	self.getWindow = function()
	{
		alert("WindowButtonDiv.getWindowにPopupDivを返すfunctionを設定してください");
	};
	self.setupWindow = function(win){};
	self.showWindow = function(win)
	{
		alert("WindowButtonDiv.getWindowにwinを表示するfunctionを設定してください");
	};

	return self;
}

/**
 * cookieをセットする
 * @param key
 * @param val
 * @param minutes 有効期限は何分後？
 */
function setCookie(key,val,minutes){
	var d = new Date();
	d.setTime(d.getTime() + minutes*60*1000);
	document.cookie = key+"="+val+";expires=" + d.toGMTString()+";";
}
/**
 * cookieの値を読む
 * @param key
 * @return val
 */
function getCookie(key){
    var tmp = document.cookie+";";
    var tmp1 = tmp.indexOf(key,0);
    if(tmp1 != -1){
        tmp = tmp.substring(tmp1,tmp.length);
        var start = tmp.indexOf("=",0);
        var end = tmp.indexOf(";",start);
        return unescape(tmp.substring(start+1,end));
    }
    return null;
}
