var FilmStrip = Class.create();

FilmStrip.prototype = {
	initialize: function(container) {
		this.imageMargin = 3;
		this.container = container;
		this.imagesLoaded = 0;
		this.allImagesLoaded = false;
		this.dragging = false;

		this.window = document.createElement('div');
		var imgHTML = this.container.innerHTML;
		this.container.innerHTML = '';
		this.window.innerHTML = imgHTML;
		Element.addClassName(this.window,'window');
		this.container.appendChild(this.window);
		this.images = this.window.getElementsByTagName('img');
		
		this.cover = document.createElement('div');
		this.container.appendChild(this.cover);
		Element.addClassName(this.cover,'cover');
		this.cover.innerHTML = 'loading...';
		
		this.controls = document.createElement('div');
		this.container.appendChild(this.controls);
		this.controls.id = 'filmStripControls';
		this.controls.style.display = 'none';
		new Ajax.Updater(this.controls,'/js/filmstrip/controls.html',{method:'get'});

		// to deal with IE image loading bug, we poll in addition to using onload handler
		this.loadPE = new PeriodicalExecuter(this._checkImagesLoaded.bind(this),0.5);

		var imageLoaders = [];
		for (i=0; i<this.images.length; i++) {
			imageLoaders[i] = new Image();
			imageLoaders[i].onload = this._imageLoaded.bind(this);
			imageLoaders[i].src = this.images[i].src;
		}
		
		Event.observe(this.container,'mousedown', this.mousedown.bind(this));
		Event.observe(this.container,'mousemove', this.mousemove.bind(this));
		Event.observe(this.container,'mouseup', this.mouseup.bind(this));
	},
	_checkImagesLoaded: function() {
		for (i=0; i<this.images.length; i++) {
			if (!this.images[i].complete)
				return;
		}
		
		this._loadComplete();
	},
	_imageLoaded: function() {
		this.imagesLoaded++;
		if (this.imagesLoaded == this.images.length) {
			this._loadComplete();
		}
		else {
			this.cover.innerHTML = 'loading...';
		}
	},
	_loadComplete: function() {
		if (this.allImagesLoaded)	// only run this once
			return;

		this.allImagesLoaded = true;
		this.loadPE.stop();
		
		var nextX = 0;
		for (var i=0; i<this.images.length; i++) {
			this.images[i].style.display = 'block';
			this.images[i].style.left = nextX+'px';
			this.images[i].style.zIndex = 1;
			this.images[i].myLeft = nextX;
			nextX += Element.getWidth(this.images[i]) + this.imageMargin;
		}
		this.totalImageWidth = nextX;
		this.leftIndex = 0;

		new Effect.Fade(this.cover, {duration: 1.0, afterFinish: this._firstStart.bind(this)});
		new Effect.Appear(this.controls, {duration: 1.0});
	},
	_firstStart: function() {
		this.start();
	},
	
	mousedown: function(event) {
		this.dragging = true;
		this.clickX = Event.pointerX(event);
		Event.stop(event);
	},
	mousemove: function(event) {
		var pointerX = Event.pointerX(event);
		if(this.dragging) {
			if (this.jumpPe != null) this.jumpPe.stop();
			for(var i=0; i<this.images.length; ++i) {
				this.images[i].myLeft += pointerX - this.clickX;
				this.images[i].style.left = this.images[i].myLeft+'px';
			}
			this.clickX = pointerX;
			this.loopcheck();
		}
		Event.stop(event);
	},
	mouseup: function(event) {
		this.dragging = false;		
		Event.stop(event);
	},
	
	start: function() {
		if (this.jumpPe != null) this.jumpPe.stop();
		this.pe = new PeriodicalExecuter(this.scroll.bind(this),0.05);
		this.moving = true;
	},
	stop: function() {
		this.moving = false;
		this.pe.stop();
	},
	isMoving: function() {
		return this.moving;
	},
	
	scroll: function() {
		if (!this.dragging) {
			for (var i=0; i<this.images.length; i++) {
				this.images[i].myLeft-= 1;
				this.images[i].style.left = this.images[i].myLeft+'px';
			}
			this.loopcheck();
		}
	},
	
	scrollToImage: function(idx) {
		if (this.isMoving()) {
			this.stop();
			Element.removeClassName('filmStripToggle','play');
		}

		this.scrollToIndex = idx;
		this.scrollToX = Math.floor((this.container.getWidth()-this.images[idx].getWidth())*0.5);
		if (this.jumpPe != null) this.jumpPe.stop();
		this.jumpPe = new PeriodicalExecuter(this._scrollToImage.bind(this),0.025);
	},
	_scrollToImage: function() {
		var scrollImage = this.images[this.scrollToIndex];
		var delta = 2;
		var inc;
		if (Math.abs(scrollImage.myLeft-this.scrollToX) < delta) {
			inc = scrollImage.myLeft-this.scrollToX;
			this.jumpPe.stop();
		}
		else {
			delta = Math.ceil((scrollImage.myLeft-this.scrollToX) * 0.1);
			inc = delta;
		}
		for (var i=0; i<this.images.length; i++) {
			this.images[i].myLeft-= inc;
			this.images[i].style.left = this.images[i].myLeft+'px';
		}
		this.loopcheck();
	},
	nextImage: function() {
		// determine which is the "next" image
		// find the center of the strip
		var center = this.container.getWidth()/2;
		// the next image whose myLeft is greater than this is it.  start with image at leftIndex
		var theImage = this.images[this.leftIndex];
		var counter = 0;
		var theIndex;
		while (theImage.myLeft < center) {
			counter++;
			theIndex = (this.leftIndex+counter) % this.images.length;
			theImage = this.images[theIndex];
		}
		this.scrollToImage(theIndex);
	},
	previousImage: function() {
		// determine which is the "previous" image
		// find the center of the strip
		var center = this.container.getWidth()/2;
		// the next image whose myLeft is greater than this is it.  start with image at leftIndex
		var theImage = this.images[this.leftIndex];
		var counter = 0;
		var theIndex;
		while (theImage.myLeft < center) {
			counter++;
			theIndex = (this.leftIndex+counter) % this.images.length;
			theImage = this.images[theIndex];
		}
		theIndex = (theIndex+this.images.length-2) % this.images.length;
		this.scrollToImage(theIndex);
	},
	
	loopcheck: function() {
		var leftImage = this.images[this.leftIndex];
		if(leftImage.myLeft < -leftImage.getWidth()) {
			leftImage.myLeft += this.totalImageWidth;
			leftImage.style.left = leftImage.myLeft+'px';
			this.leftIndex = (this.leftIndex+1) % this.images.length;
		}
		else if(leftImage.myLeft > 0) {
			var rightIndex = (this.leftIndex+(this.images.length-1)) % this.images.length;
			var rightImage = this.images[rightIndex];
			rightImage.myLeft -= this.totalImageWidth;
			rightImage.style.left = rightImage.myLeft+'px';
			this.leftIndex = rightIndex;
		}
	}
}

var strip;

function initFilmStrip() {
	var stripDiv = $('filmStrip');
	if (stripDiv != null) {
		strip = new FilmStrip($('filmStrip'));
	}
}

function toggleMovement() {
	if (strip.isMoving()) {
		strip.stop();
		Element.removeClassName('filmStripToggle','play');
	}
	else {
		strip.start();
		Element.addClassName('filmStripToggle','play');
	}
}

function nextImage() {
	strip.nextImage();
}
function previousImage() {
	strip.previousImage();
}

Event.observe(window,'load',initFilmStrip);