jQuery.fn.extend({
    imageViewer: function() {
	    return this.each(function() {
	        new jQuery.imageViewer(this);
	    });
	}
});

jQuery.extend({
	imageViewer: function(e) {
		var priv = {
			scope: null,
			container: null,
			list: null,
			contentHeight: null,
			percentInView: null,
			paneWidth: null,
			paneHeight: null,
			currentArrowButton: null,
			currentArrowDirection: null,
			currentArrowInterval: null,
			currentArrowInc: null,
			mouseWheelSpeed: null,
			scrollPosition: 0,
			destY: null,
			autoScrollInterval: null,
			autoScrollDirection: 1,
			autoScrollSpeed: null,
			elemHeight: null,
			middleElem: 1,
			scrollTop: null,
			currentElem: 1,
			listLength: null,
			intervalCount: 1,
			prepare: function(e) {
				priv.container = jQuery(e).parent();
				priv.list = jQuery('ul', priv.container);
				priv.paneWidth = priv.container.innerWidth();
				priv.paneHeight = priv.container.outerHeight();
				priv.elemHeight = jQuery('li', priv.list).outerHeight();
				priv.list.css(
					{
						'top': 0,
						'height':'auto',
						'width': priv.paneWidth + 'px'
					}
				);
				priv.contentHeight = jQuery(priv.list).outerHeight();
				priv.percentInView = priv.paneHeight / priv.contentHeight;
					
				priv.mouseWheelSpeed = 2 * 16 * priv.paneHeight / priv.contentHeight;
				//priv.autoScrollSpeed = 2 * priv.paneHeight / priv.contentHeight;
				priv.autoScrollSpeed = '.2';
				jQuery(priv.container).wrap(
					jQuery('<div>').css(
						{
							'width': priv.paneWidth+'px',
							'height':priv.paneHeight+'px'
						}
					)
				);
				jQuery(priv.container).css({'float':'none'});
				priv.scope = jQuery(priv.container).parent();
				jQuery(priv.scope).prepend(
						jQuery('<a>')
							.attr({'href':'javascript:;', 'className':'imageViewerArrowUp'})
							//.css({'height': '17px'})
							.html('Scroll up')
							.bind('mousedown', function()
							{
								priv.currentArrowButton = this;
								priv.currentArrowDirection = -1;
								priv.onArrowMouseDown();
								this.blur();
								return false;
							})
					);
				jQuery(priv.scope).append(
						jQuery('<a>')
							.attr({'href':'javascript:;', 'className':'imageViewerArrowDown'})
							//.css({'height': '17px'})
							.html('Scroll down')
							.bind('mousedown', function()
							{
								priv.currentArrowButton = this;
								priv.currentArrowDirection = 1;
								priv.onArrowMouseDown();
								this.blur();
								return false;
							})
					);
				jQuery(priv.list).css({'position':'absolute', 'overflow':'visible'});
				jQuery('li a img', priv.list).click(priv.selectImage);
				jQuery(priv.scope).parent().parent().bind('mouseover', priv.stopAutoScroll);
				jQuery(priv.scope).parent().parent().bind('mouseout', priv.startAutoScroll);
			},
			
			whileArrowButtonDown: function() {
				priv.positionDrag( priv.scrollPosition + priv.currentArrowDirection * priv.mouseWheelSpeed);
			},
			onArrowMouseUp: function(event) {
				jQuery('body').unbind('mouseup', priv.onArrowMouseUp);
				jQuery(priv.currentArrowButton).removeClass('imageViewerActiveArrowButton');
				clearInterval(priv.currentArrowInterval);
			},
			onArrowMouseDown: function() {
				jQuery('body').bind('mouseup', priv.onArrowMouseUp);
				jQuery(priv.currentArrowButton).addClass('imageViewerActiveArrowButton');
				priv.currentArrowInc = 0;
				priv.whileArrowButtonDown();
				priv.currentArrowInterval = setInterval(priv.whileArrowButtonDown, 100);
			},
			
			positionDrag: function(destY) {
				if (priv.contentHeight < priv.paneHeight)
					return;
				destY = destY < 0 ? 0 : (destY > priv.paneHeight ? priv.paneHeight : destY);
				priv.scrollPosition = destY;
				var p = destY / priv.paneHeight;
				priv.scrollTop = ((priv.paneHeight - priv.contentHeight)*p);
				jQuery(priv.list).css({'top': priv.scrollTop + 'px'});
			},
			
			selectImage: function() {
				jQuery(this).TransferTo ({to:'theImg',className:'transferer', duration: 500, complete: priv.changeImage});
				return false;
			},
			
			changeImage: function(imageId) {
				if (typeof imageId == 'object') {
					var imageId = parseInt(jQuery(this).parents('li').attr('id').slice(6)) - 1;
				}
				var imageHolder = jQuery('#theImg');
				
				imageHolder.after(
					jQuery('<img>').attr('src',jQuery('li:eq(' + imageId + ') a img', priv.list).attr('src'))
						.attr('id', 'theImg').attr('width', '320').attr('height', '240')
				);
				imageHolder.parent().attr('href', jQuery('li:eq(' + imageId + ') a', priv.list).attr('href'));
				jQuery('li a img', priv.list).removeClass('currentImage');
				jQuery('li:eq(' + imageId + ') a img', priv.list).addClass('currentImage');
				priv.currentElem = imageId;
				imageHolder.remove();
			},
			prevImage: function() {
				var prevImage = priv.currentElem - 1;
				jQuery('li:eq('+ prevImage + ') a img', priv.list).trigger('click');
				return false;
			},
			nextImage: function() {
				var nextImage = priv.currentElem + 1;
				jQuery('li:eq('+ nextImage + ') a img', priv.list).trigger('click');
				return false;
			},
			startAutoScroll: function() {
				priv.autoScrollInterval = setInterval(priv.autoScroll, 100);
			},
			stopAutoScroll: function() {
				clearInterval(priv.autoScrollInterval);
			},
			autoScroll: function() {
				if (priv.scrollPosition == 0 && ( (priv.autoScrollDirection == 1 && priv.currentElem <= 1) || (priv.autoScrollDirection == -1  && priv.currentElem <= 2) ) ) {
					priv.intervalCount = priv.intervalCount + 1;
					if (priv.intervalCount > 50) {
						if (priv.autoScrollDirection == 1) {
								jQuery('li:eq(' + (priv.currentElem + 1) + ') a img', priv.list).trigger('click');
								priv.intervalCount = 0;
						} else {
							jQuery('li:eq(' + (priv.currentElem - 1) + ') a img', priv.list).trigger('click');
							if (priv.currentElem <= 0) {
									priv.autoScrollDirection = 1;
							}
							priv.intervalCount = 0;
						}
					}
				} else if (priv.scrollPosition == priv.paneHeight && ( priv.autoScrollDirection == 1 || (priv.autoScrollDirection == -1  && priv.currentElem >= jQuery('li', priv.list).length - 2) ) ) {
					priv.intervalCount = priv.intervalCount + 1;
					if (priv.intervalCount > 50) {
						if (priv.autoScrollDirection == 1) {
							if (jQuery('li', priv.list).length == (priv.currentElem + 1)) {
								priv.autoScrollDirection = -1;
							} else {
								jQuery('li:eq(' + (priv.currentElem + 1) + ') a img', priv.list).trigger('click');	
								priv.intervalCount = 0;
							}
						} else {
							jQuery('li:eq(' + (priv.currentElem - 1) + ') a img', priv.list).trigger('click');
							priv.intervalCount = 0;
						}
					}
				} else {
					priv.positionDrag( priv.scrollPosition + priv.autoScrollDirection * priv.autoScrollSpeed);
					var middlePos = priv.scrollTop * -1 + (priv.paneHeight / 2);
					var middleElem = Math.round(middlePos / priv.elemHeight - 0.5);
					
					if (middleElem != priv.middleElem) {
						priv.middleElem = middleElem;
						if (priv.currentElem != priv.middleElem && (priv.autoScrollDirection == 1 && (priv.middleElem > priv.currentElem) ) || (priv.autoScrollDirection == -1 && (priv.middleElem < priv.currentElem)) )
							jQuery('li:eq(' + priv.middleElem + ') a img', priv.list).trigger('click');
					}
				}
			}
		};
		
		priv.prepare(e);
		priv.changeImage(0);
		$('#prev').click(priv.prevImage);
		$('#next').click(priv.nextImage);
		priv.startAutoScroll();
	}
});

$(function () {
	$('#imageHolder').imageViewer();
	$('a#enlarge').click(function() {
		$('#theImg').parent().trigger('click');
		this.blur();
		return false;
	});
});

