if (navigator.userAgent.toLowerCase().indexOf('gecko') == -1) {
	alert('Warning: this is a firefox only experiment');
}

Math.PI = 3.14159;

var JsPano = Class.create();
JsPano.prototype = {
	initialize: function(id,imgWidth,imgHeight,windowWidth,windowHeight,sliceWidth, curvature) {
		this.id = id;
		this.imgWidth = imgWidth;
		this.imgHeight = imgHeight;
		this.windowWidth = windowWidth;
		this.windowHeight = windowHeight;
		this.sliceWidth = sliceWidth;
		this.curvature = curvature;
		if (this.curvature == undefined)
			this.curvature = 1.8;

		this.timeoutBinding = this.fireTimeout.bind(this);

		// TODO, make these configurable
		this.is360 = true;
		this.maxXSpeed = 10;
		this.frequency = 50;
		
		// internal
		this.currentXPos = 0;
		this.currentYPos = 0;
		this.currentXSpeed = 5;	
		this.innerSlices = [];
					
		// begin
		var img = document.getElementById(id);
		this.imgUrl = img.src;
		
		this.container = document.createElement('div');
		this.container.className = 'container';
		this.container.style.width = this.windowWidth;	
		this.container.style.height = this.imgHeight;	
		this.container.style.position = 'relative';
		img.parentNode.insertBefore(this.container,img);
		img.parentNode.removeChild(img);
		
		this.numberOfSlices = this.windowWidth / this.sliceWidth;
		
		for (var i=0; i<this.numberOfSlices; i++) {
			
			// the slice is like a mask for the image.			
			var slice = document.createElement('div');
			slice.setAttribute('id',id + '-slice-' + i);
			slice.className = 'slice';
			slice.style.position = 'absolute';
			slice.style.top = 0;
			slice.style.left = (this.sliceWidth * i) + 'px';
			slice.style.width = this.sliceWidth + 'px';
			slice.style.height = this.imgHeight + 'px';
			slice.style.overflow = 'hidden';			
			this.container.appendChild(slice);
			
			// inner div that can be moved
			var innerSlice = document.createElement('div');
			innerSlice.setAttribute('id',id + '-innerslice-' + i);
			innerSlice.style.position = 'absolute';
			innerSlice.style.top = 0;
			innerSlice.style.left = (this.sliceWidth * i) + 'px';
			innerSlice.style.width = (this.imgWidth*2) + 'px';
			innerSlice.style.height = this.imgHeight + 'px';
			slice.appendChild(innerSlice);			
			
			// two images!
			var leftImg = document.createElement('img');
			leftImg.height = this.imgHeight;
			leftImg.width = this.imgWidth;
			leftImg.style.position = 'absolute';
			leftImg.style.top = 0;
			leftImg.style.left = 0;
			leftImg.src = this.imgUrl;			
			innerSlice.appendChild(leftImg);
			
			var rightImg = document.createElement('img');
			rightImg.height = this.imgHeight;
			rightImg.width = this.imgWidth;
			rightImg.style.position = 'absolute';
			rightImg.style.top = 0;
			rightImg.style.left = this.imgWidth;
			rightImg.src = this.imgUrl;			
			innerSlice.appendChild(rightImg);			
						
			this.innerSlices.push(innerSlice);			
		}
		
		this.moveTo(0,0);
		this.start();				
		
		Event.observe(window,'mousemove',this.mouseMove.bind(this));
	},

	
	moveBy: function(x,y) {
		var newX = this.currentXPos + x;
		
		if (newX < 0)  {
			newX = this.imgWidth - newX;
		} else if (newX > this.imgWidth ) {
			newX = newX - this.imgWidth ;
		}
		
		//alert(newX);
		this.moveTo(newX,0);
	},
	
	mouseMove: function(event) {
				
		// check if inside window
		var pos = Position.cumulativeOffset(this.container);
	
		if ( 
			event.clientY >= pos[1] &&
            event.clientY <  pos[1] + this.container.offsetHeight &&
            event.clientX >= pos[0] &&
            event.clientX <  pos[0] + this.container.offsetWidth) {
			
			// adjust speed based on the 
			this.currentXSpeed = ( (event.clientX-pos[0]) - (this.container.offsetWidth/2) ) / (this.container.offsetWidth/2) * this.maxXSpeed;            
		}
	},
	
	// ypos not used
	moveTo: function(xpos,ypos) {
		if (xpos < 0)
			return;
	
		if (!this.is360 && xpos > this.imgWidth - this.windowWidth)
			return;
					
		this.currentXPos = xpos;
		
		
		
		var timer1 = new Date();
		
		for (var i=0; i<this.innerSlices.length; i++) {
			var innerSlice = this.innerSlices[i];
			
			// calculate the scale
			var xPoint = i-this.numberOfSlices/2;	
			var yScale = (( Math.abs( (Math.cos(Math.abs(xPoint)/this.numberOfSlices/2 * Math.PI))-1)*this.curvature  )+1) 
			
			// scale both images inside the slice
			var lImg = innerSlice.childNodes[0];
			var rImg = innerSlice.childNodes[1];
			lImg.height = rImg.height = this.imgHeight * yScale;
			lImg.style.top = rImg.style.top = -Math.abs(lImg.height-this.imgHeight)/2;

			innerSlice.style.left = -(this.sliceWidth * i) - xpos;
		}
		
		//$('Debug').innerHTML = new Date() - timer1;
	},
	
	fireTimeout: function() {
				
		this.moveBy(this.currentXSpeed);
		clearTimeout(this.timer);
		
		if (this.continue) {
			this.start();
		}
	},
	
	start: function() {
		this.timer = setTimeout( this.timeoutBinding, this.frequency);	
		this.continue = true;
	},
	
	stop: function() {
		this.continue = false;
	}
};

var pano = new JsPano('Courtyard',1240,300,350,300,5);

