(function($) {
	$.widget('ui.timeline', {
		_init: function() {
			this.items = $(this.options.items, this.element);
			this.itemWidth = this.items.eq(0).width();
			this.itemHeight = this.items.eq(0).height();
			this.scale = this.options.scale;
			this.fade = this.options.fade;
			this.fadeTo = this.options.fadeTo;
			this.offset = this.options.offset;
			this.selected = this.options.selected;
			this.speed = this.options.speed;
			this.previous = this.options.previous;
			this.next = this.options.next;
			this.slider = this.options.slider;
			this.onShow = this.options.onShow;
			this.offStagePosition = null;
			
			if (this.element.css('position') == 'static') this.element.css('position', 'relative');			
			this.element.css('overflow', 'hidden');
			this.element.css('z-index', 0);
			this.items.css('position', 'absolute');
			
			var self = this;
			
			if (this.fade != 0) {
				this.items.append('<div class="ui-timeline-mask"></div>');
				this.element.find('.ui-timeline-mask').css({
					position: 'absolute',
					top: 0,
					left: 0,
					width: self.itemWidth,
					height: self.itemHeight,
					backgroundColor: self.fadeTo
				});
			}
			
			$(document).keydown(function(e) {
				if(e.keyCode == 37 && self.selected -1 >= 0) {
					self.reverse();
				}
				if (e.keyCode == 39 && self.items.length > self.selected + 1) {
					self.forward();
				}
			});
			
			if (this.previous) {
				$(this.previous).click(function() {
					self.reverse();
					return false;
				});
			}
			
			if (this.next) {
				$(this.next).click(function() {
					self.forward();
					return false;
				});
			}
			
			this.items.click(function() {
				self.selected = $(self.items).index(this);
				if (self.slider != false) $(self.slider).slider('value', self.selected);
				self.refresh(true);
			});
			
			if (self.slider) {
				$(this.slider).slider({
					min: 0,
					max: self.items.length - 1,
					noKeyboard: true,
					animate: true,
					step: 1,
					slide: function(e, ui) {
						self.selected = ui.value;
						self.refresh(true);
					},
					stop: function(e, ui) {
						self.refresh();
					}
				});
			}
			
			this.refresh();
		},
		
		refresh: function(animate) {
			var self = this;
			this.items.each(function(i) {
				var $item = $(this);
				if ($item.css('display') == 'none') return true;
				var position = Math.abs(self.selected - i);
				if (self.offStagePosition != null && position > self.offStagePosition) {
					$item.css({
						left: i <= self.selected ? 20000 : -20000
					});
				} else {
					var width = self.itemWidth * Math.pow(self.scale, position);
					var left = 0;
					if (i <= self.selected) {
						var offset = 0;
						for (var j = 0; j < position; j++) {
							offset += self.itemWidth * Math.pow(self.scale, j - 1) * self.offset;
						}
						left = self.element.width() / 2 - offset;
						left -= self.itemWidth / 2;
						if (self.offStagePosition == null && left + width < self.element.position().left) {
							self.offStagePosition = position;
						}
					} else {
						var offset = 0;
						for (var j = 0; j < position; j++) {
							offset += self.itemWidth * Math.pow(self.scale, j - 1) * self.offset + (self.itemWidth * Math.pow(self.scale, j - 1) - self.itemWidth * Math.pow(self.scale, j));
						}
						left = self.element.width() / 2 + offset;
						left -= self.itemWidth / 2;
						if (self.offStagePosition == null && left > self.element.position().left + self.element.width()) {
							self.offStagePosition = position;
						}
					}
					$item.css({
						visibility: 'visible',
						zIndex: self.items.length - self.selected - position
					});
					$item.stop().animate({
						width: width,
						height: self.itemHeight * Math.pow(self.scale, position),
						left: left,
						top: self.element.height() / 2 - (self.itemHeight * Math.pow(self.scale, position)) / 2
					}, { 
						duration: animate ? self.speed : 0, 
						complete: function() { 
							if (i == self.selected) {
								self.onShow.call(this);
							}
							self.items.removeClass('selected');
							self.items.eq(self.selected).addClass('selected');
						} 
					});
					if (this.fade != 0) {
						if (i == self.selected) {
							$item.find('.ui-timeline-mask').hide();
						} else {
							$item.find('.ui-timeline-mask').css({
								opacity: Math.min(1, self.fade * position)
							});
							$item.find('.ui-timeline-mask').show();
						}
					}
				}
			});
			if (this.previous) {
				$(this.previous).toggleClass('disabled', this.selected == 0);
			}
			if (this.next) {
				$(this.next).toggleClass('disabled', this.selected == this.items.length - 1);
			}
		},
		
		forward: function() {
			if (this.selected >= this.items.length - 1) return false;
			this.selected++;
			if (self.slider != false) $(this.slider).slider('value', this.selected);
			this.refresh(true);
			return this;
		},

		reverse: function() {
			if (this.selected <= 0) return false;
			this.selected--;
			if (self.slider != false) $(this.slider).slider('value', this.selected);
			this.refresh(true);
			return this;
		}
	});
	
	$.extend($.ui.timeline, {
		defaults: {
			items: '> *',
			scale: .9,
			fade: .8,
			fadeTo: '#000',
			offset: .2,
			selected: 0,
			speed: 'fast',
			previous: false,
			next: false,
			slider: false,
			onShow: function() {}
		}
	});

})(jQuery);
