// Copyright 2009 Intrinzyx

var SVTour2 = Class.create({

	ix: 0,	iy: 0,
	targetX: 0,	targetY: 0, targetZoom: 0,
	stepX: 0, stepY: 0,
	offsX: 0, offsY: 0,
	wrapAround: true,
	aspectRatio: 0.0,
	curWidth: 0, curHeight: 0,
	
	initialize: function(container, obj, imgUrl, imgWidth, imgHeight, numImages, viewWidth, viewHeight, options)
	{
		this.container = $(container);
		this.obj = obj;
		this.imgUrl = imgUrl;
		this.imgWidth = imgWidth;
		this.imgHeight = imgHeight;
		this.numImages = numImages;
		this.actImages = numImages;
		this.viewWidth = viewWidth;
		this.viewHeight = viewHeight;
		this.options = options || { };

		this.panStepX = this.options.panStepX || 80;
		this.panStepY = this.options.panStepY || 20;
		this.wrapAround = this.options.wrapAround;

		if (this.imgWidth < this.imgHeight)
		{
			this.aspectRatio = this.imgHeight / this.imgWidth;
		}		
		else
		{
			this.aspectRatio = this.imgWidth / this.imgHeight;
		}
		this.initHeight = this.viewHeight;
		this.initWidth = parseInt(this.viewHeight * this.aspectRatio);		
		this.zoom = 1;
		
		var html = "<div id='vtourc' class='" + this.options.cssClass + "' style='display: block; position: relative; overflow: hidden; white-space: nowrap; width:" + this.viewWidth + "; height:" + this.viewHeight + "; cursor: pointer;'>";
		html += "<div style='z-index: 1000; position: absolute; left: " + (this.viewWidth / 2) + "px; top: " + (this.viewHeight / 2) + "px; background-color: orange; width: 2px; height: 2px;'></div>"
		html += "<div id='vtouri' style='display: block; overflow: hidden; position: relative; left: 0px; top: 0px;'>";
		if (this.numImages > 1)
		{
			for(var i = 0; i < this.numImages; i++)
			{
				html += "<img id='vtour_img" + i + "' src='" + this.imgUrl + (i + 1) + ".jpg' width='" + this.initWidth + "' height='" + this.initHeight + "' />";
			}
		}
		else
		{
			html += "<img id='vtour_img0' src='" + this.imgUrl + "' width='" + this.initWidth + "' height='" + this.initHeight + "' />";
		}
		
		if (this.wrapAround)
		{
			var remainingWidth = this.viewWidth;
			var i = 0;
			while(remainingWidth > 0 && i < this.numImages)
			{
				//html += "<img style='border-left: 1px solid red' id='vtour_img" + (this.actImages) + "' src='" + this.imgUrl + (i + 1) + ".jpg' width='" + this.initWidth + "' height='" + this.initHeight + "' />";
				html += "<img id='vtour_img" + (this.actImages) + "' src='" + this.imgUrl + (i + 1) + ".jpg' width='" + this.initWidth + "' height='" + this.initHeight + "' />";
				this.actImages++;
				remainingWidth -= this.imgWidth;
				i++;
			}
		}
				
		html += "</div>";
		html += "</div>";

		this.container.innerHTML = html;		
		
		Event.observe(document, 'keydown', FunctionX.createDelegate(this, this.onKeyDown));
		
		this.vtour = $("vtouri");
		this.vtourc = $("vtourc");
		
		this.img = [];
		for(var i = 0; i < this.actImages; i++)
		{
			var el = $("vtour_img" + i);
			this.img.push(el);
		}

		if (typeof this.vtour.onselectstart != "undefined")
			this.vtour.onselectstart = function() { return false; }; /* ie */
		if (typeof this.vtour.style.MozUserSelect != "undefined")
			this.vtour.style.MozUserSelect = "none"; 				/* moz */	
			
		this.mouseMoveDelegate = FunctionX.createDelegate(this, this.onMouseMove);
		this.mouseUpDelegate = FunctionX.createDelegate(this, this.onMouseUp);
		this.mouseDownDelegate = FunctionX.createDelegate(this, this.onMouseDown);
		
		this.dragging = false;
		this.vtour.onmousedown = this.mouseDownDelegate;
		this.vtour.onmousemove = this.mouseMoveDelegate;
		
		this.zoomTo(this.zoom);
	},
	
	onMouseDown: function(evt) 
	{
		if (!evt) evt = event;
		if(evt.preventDefault)
			evt.preventDefault();
 		var mouseX = Event.pointerX(evt);
		var mouseY = Event.pointerY(evt);

		coffs = this.vtour.cumulativeOffset();
		this.offsX = mouseX + this.ix;
		this.offsY = mouseY + this.iy;

		this.dragging = true;
		ElementTrack.capture(this.mouseMoveDelegate, this.mouseUpDelegate);
		return false;
	},

	onMouseMove: function(evt) 
	{
		if (!evt) evt = event;
		var mouseX = Event.pointerX(evt);
		var mouseY = Event.pointerY(evt);

		if (this.dragging)
		{
			// TODO: Bias based on distance from center
			var x = (mouseX - this.offsX);
			var y = (mouseY - this.offsY);

			this.setPos(-x, -y);
		}
		else
		{
			coffs = this.vtourc.cumulativeOffset();
			var c = this.pointToImg(mouseX - coffs[0], mouseY - coffs[1]);
			//$("s").innerHTML = "img(" + c.x + "," +c.y +")";
			//$("s").innerHTML = "img(" + (mouseX - coffs[0]) + "," + (mouseY - coffs[1]) +")";
		}
			
		return false;
	},

	onMouseUp: function(evt) 
	{
		this.dragging = false;
		ElementTrack.release();
	},

	onKeyDown: function(e)
	{
		var code;
		if (!e) var e = window.event;
		if (e.keyCode) code = e.keyCode;
		else if (e.which) code = e.which;
		
		switch(code)
		{
			case Event.KEY_LEFT:
				this.panLeft();
				break;
			case Event.KEY_RIGHT:
				this.panRight();
				break;
			case Event.KEY_UP:
				this.panUp();
				break;
			case Event.KEY_DOWN:
				this.panDown();
				break;
			case 107: // +
				this.zoomIn();
				break;
			case 109: // -
				this.zoomOut();
				break;
		}
		
		//$("k").innerHTML = code;
	},
					
	panLeft: function()
	{
		this.panTo(this.ix - this.panStepX * this.zoom, this.iy);
	},
	
	panRight: function()
	{
		this.panTo(this.ix + this.panStepX * this.zoom, this.iy);
	},
	
	panUp: function()
	{
		this.panTo(this.ix, this.iy - this.panStepY * this.zoom);
	},
	
	panDown: function()
	{
		this.panTo(this.ix, this.iy + this.panStepY * this.zoom);
	},
	
	panTo: function(x, y)
	{
		this.stepX = Math.floor((x - this.ix) / (4 * this.zoom));
		this.stepY = Math.floor((y - this.iy) / (4 * this.zoom));

		var c = this.clamp(x, y);
		this.targetX = c.x;
		this.targetY = c.y;

		//$("s").innerHTML = "target: " + this.targetX + ", " + this.targetY + " : " + this.stepX + ", " + this.stepY + " : " + this.ix + ", " + this.iy;
		
		this.setPos(this.targetX, this.targetY);
		return;
		
		//if (Prototype.Browser.IE)
			//this.setPos(this.targetX, this.targetY);
		//else
			this.animatePan();
	},
	
	animatePan: function()
	{
	
	//$("s").innerHTML += "<br>a: " + this.ix + ", " + this.iy;
	
		if (this.ix == this.targetX && this.iy == this.targetY)
			return;
			
		if ((this.stepX < 0 && this.ix <= this.targetX) || (this.stepX > 0 && this.ix >= this.targetX))
		{
			this.stepX = 0;
			this.ix = this.targetX;
	//$("s").innerHTML += "<br>xb";
		}
		
		if ((this.stepY < 0 && this.iy <= this.targetY) || (this.stepY > 0 && this.iy >= this.targetY))
		{
			this.stepY = 0;
			this.iy = this.targetY;
	//$("s").innerHTML += "<br>yn";
		}		

		this.setPos(this.ix + this.stepX, this.iy + this.stepY);
		setTimeout(this.obj + ".animatePan()", 1);
	},

	setPos: function(x, y)
	{
		var c = this.clamp(x, y);
		this.ix = c.x;
		this.iy = c.y;
		
		this.vtour.style.left = -this.ix + "px";
		this.vtour.style.top = -this.iy + "px";

		//$("s").innerHTML += "<br>" + this.ix + ", " + this.iy + " zoom: " + this.zoom;
	},

	zoomIn: function()
	{
		this.zoomTo(this.zoom + 1);
	},
	
	zoomOut: function()
	{
		this.zoomTo(this.zoom - 1);
	},
	
	zoomTo: function(z)
	{
		this.setZoom(z);
		return;
		
		this.targetZoom = z;
		this.zoomStep = z < this.targetZoom ? -1 : 1;
		this.animateZoom();
	},
	
	setZoom: function(z)
	{
		if (z < 1)
			z = 1;
		else if (z > 10)
			z = 10;

		var oldZoom = this.zoom;
		var oldWidth = this.curWidth;
		var oldHeight = this.curHeight;
					
		this.zoom = z;
		//this.curContWidth = z * this.initWidth * this.actImages;
		//this.curActContWidth = z * this.initWidth * this.numImages;
		if (this.imgWidth < this.imgHeight)
		{
			this.curHeight = z * this.initHeight;
			this.curWidth = this.curHeight / this.aspectRatio;
		}
		else
		{
			this.curWidth = z * this.initWidth;
			this.curHeight = this.curWidth / this.aspectRatio;
		}
		
		this.curContWidth = this.curWidth * this.actImages;
		this.curActContWidth = this.curWidth * this.numImages;
		
		this.vtour.style.width = this.curContWidth + "px";
		for(var i = 0; i < this.actImages; i++)
		{
			this.img[i].style.width = this.curWidth + "px";
			this.img[i].style.height = this.curHeight + "px";
		}
		
		// Keep centered on the same spot
		if (this.zoom != oldZoom)
		{	
			var vcx = parseInt(this.viewWidth / 2);
			var vcy = parseInt(this.viewHeight / 2)
			
			var oldCenterX =  parseInt((this.ix + vcx) / oldZoom);
			var oldCenterY = parseInt((this.iy + vcy) / oldZoom);
			
			var newCenterX = oldCenterX * this.zoom;
			var newCenterY = oldCenterY * this.zoom;
			
			var nx = newCenterX - vcx;
			var ny = newCenterY - vcy;
					
			this.setPos(nx, ny);			
		}
		
		//$("s").innerHTML = this.zoom;
	},	
	
	pointToImg: function(px, py)
	{
		px = (this.zoom * px) + this.ix;
		py = (this.zoom * py) + this.iy;
		return { x: px, y: py };
	},
	
	imgToPoint: function(ix, iy)
	{
		ix = (ix - this.ix) / this.zoom;
		iy = (iy - this.iy) / this.zoom;
		return { x: ix, y: ix };
	},
	
	animateZoom: function()
	{
		if (this.zoom == this.targetZoom)
			return;
			
		this.setZoom(this.zoom + this.zoomStep);
		setTimeout(this.obj + ".animateZoom()", 10);
	},
	
	clamp: function(px, py)
	{
		if (this.wrapAround)
		{
			if (px > this.curActContWidth)
				px -= this.curActContWidth;
			else if (px < 0 )
				px += this.curActContWidth;
		}
		else
		{
			if (px > this.curActContWidth - this.viewWidth)
				px = this.curActContWidth - this.viewWidth;
			if (px < 0)
				px = 0;
		}

		if (py > this.curHeight - this.viewHeight)
			py = this.curHeight - this.viewHeight;			
		if (py < 0)
			py = 0;
			
		return { x: px, y: py };
	},
	
	onControl: function(id)
	{
		$(id).src = "images/" + id + "S.jpg";
	},
	
	offControl: function(id)
	{
		$(id).src = "images/" + id + ".jpg";
	}
});
