$.jqCarousel = {
	defaults:{
		autoplay:false,
		width:848,
		height:295,
		items: 'div',
		itemWidth: 848,
		itemHeight: 261,
		itemSpacing: 0,
		itemStart: 1,
		offset: 0,
		multiply: 1,
		delay: 5000,
		speed: 1000,
		direction:'top',
		easeIn: 'swing',
		onScroll: function(ui){},
		onStart: function(ui){},
		onEnd: function(ui){}
	},
	setOptions: function(options){
		var opts = this.defaults;
		for(var x in options){
			if(typeof opts[x] === 'undefined') alert('Invalid option '+x);
			else opts[x] = (opts[x] != null && opts[x].constructor == Object)? this.setOptions(options[x], opts[x]) : options[x];
		}
		return opts;
	},
	initVars: function(obj){
		var pos = obj.element.css('position');
		pos = (pos != 'relative' && pos != 'absolute')? 'relative' : pos;
		if(!obj.options.width) obj.options.width = obj.element.outerWidth();
		if(!obj.options.height) obj.options.height = obj.element.outerHeight();
		obj.wrapper = $('<div class="carouselWrap" />').css({width:obj.options.width, height:obj.options.height, position:pos, overflow:'hidden'});
		obj.element.css({width:obj.options.width, height:obj.options.height, position:pos, overflow:'hidden'});
		obj.element.wrap( obj.wrapper );
		obj.items = $(obj.options.items, obj.element);
		if(!obj.options.itemWidth) obj.options.itemWidth = obj.items.outerWidth();
		if(!obj.options.itemHeight) obj.options.itemHeight = obj.items.outerHeight();
		obj.items.css({width:obj.options.itemWidth, height:obj.options.itemHeight, position:'absolute', overflow:'hidden'});
		obj.options.itemWidth = obj.items.outerWidth();
		obj.options.itemHeight = obj.items.outerHeight();
		obj.element.after(obj.next);
		obj.element.after(obj.prev);
		obj.direction = obj.options.direction;
		obj.index = (obj.options.itemStart<=obj.items.length)? obj.options.itemStart-1 : obj.options.itemStart%obj.items.length-1;
	},
	initItems: function(obj){
		var o = obj.options, j = obj.items.length;
		switch(o.direction){
			case 'left': case 'right':
				obj.scrollBy = parseInt(o.itemWidth) + parseInt(o.itemSpacing);
				obj.items.css('top',0);
			break;
			case 'top': case 'bottom':
				obj.scrollBy = parseInt(o.itemHeight) + parseInt(o.itemSpacing);
				obj.items.css('left',0);
			break
		}
		obj.scrollAmount = obj.scrollBy * parseInt(o.multiply);
		if(o.offset.toString().match(/\%/)) obj.options.offset = Math.floor((parseInt(o.offset)*obj.scrollBy)/100);
		var dim = obj.scrollBy;
		var diff = (o.offset<0)? (o.itemStart-1)+ -Math.ceil(o.offset/dim) : (o.itemStart-1)+ j-Math.ceil(o.offset/dim);
		var off = (o.offset<0)? o.offset%dim : o.offset>0? (o.offset%dim)-dim : 0;
		obj.max = dim*(j-1)+off;
		for(var i=0; i<j; i++){
			switch(o.direction){
				case 'left': case 'top' : $(obj.items[(diff+i)%j]).css(o.direction, dim*i+off); break;
				case 'right' : $(obj.items[(diff+i)%j]).css('left', o.width - (dim*i+off) - o.itemWidth); break;
				case 'bottom' : $(obj.items[(diff+i)%j]).css('top', o.height - (dim*i+off) - o.itemHeight); break;
			}
		}
		if($.isFunction(o.onStart)) o.onStart.apply(this,[obj, obj.items[obj.index]]);
	},
	initEvents: function(obj){
		obj.next.bind('click', function(){
			obj.options.direction = obj.direction;
			$.each(obj.items, function(i,item){ $.jqCarousel.resetItem(obj, item); });
			obj.scrollDir = 1;
			if(!obj.options.autoplay) $.jqCarousel.scrollImages(obj);
		});
		obj.prev.bind('click', function(){
			switch(obj.direction){
				case 'left': obj.options.direction = 'right'; break;
				case 'right': obj.options.direction = 'left'; break;
				case 'top': obj.options.direction = 'bottom'; break;
				case 'bottom': obj.options.direction = 'top'; break;
			}
			$.each(obj.items, function(i,item){ $.jqCarousel.resetItem(obj, item); });
			obj.scrollDir = -1;
			if(!obj.options.autoplay) $.jqCarousel.scrollImages(obj);
		});
		if(obj.options.autoplay){
			obj.element.bind('mouseenter', function(){$.jqCarousel.stop(obj);} );
			obj.element.bind('mouseleave', function(){$.jqCarousel.play(obj);} );
			$.jqCarousel.play(obj, 2000);
		}
	},
	scrollImages:function(obj){
		var o = obj.options, s = parseInt(o.speed),	d = parseInt(o.delay), a = obj.scrollAmount;
		if($.isFunction(o.onScroll)) o.onScroll.apply(this,[obj, obj.items[obj.index]]);
		switch(o.direction){
			case 'left':
				obj.items.animate({'left': '-='+ a}, s, o.easeIn, function(){$.jqCarousel.resetItem(obj, this); $.jqCarousel.onEnd(obj, this); });
			break;
			case 'right':
				obj.items.animate({'left': '+='+ a}, s, o.easeIn, function(){$.jqCarousel.resetItem(obj, this); $.jqCarousel.onEnd(obj, this); });
			break;
			case 'top':
				obj.items.animate({'top': '-='+ a}, s, o.easeIn, function(){$.jqCarousel.resetItem(obj, this); $.jqCarousel.onEnd(obj, this); });
			break;
			case 'bottom':
				obj.items.animate({'top': '+='+ a}, s, o.easeIn, function(){$.jqCarousel.resetItem(obj, this); $.jqCarousel.onEnd(obj, this); });
			break;
		}
		if(obj.playing) obj.timer = setTimeout(function(){$.jqCarousel.scrollImages(obj);}, s+d+100);
		obj.index = obj.index + (o.multiply*obj.scrollDir);
		obj.index = (obj.index>0)? obj.index%obj.items.length : obj.index<0? obj.items.length+obj.index : 0;
	},
	resetItem:function(obj, item){
		var o = obj.options;
		var x = obj.scrollBy * 1;
		switch(o.direction){
			case 'left': 
				var p = parseInt($(item).css('left')) || 0;
				if(p <= 0-o.itemWidth){
					$(item).css('left', obj.max + x + p - o.offset);
				}
			break;
			case 'right':
				var p = parseInt($(item).css('left')) || 0;
				if(p >= o.width){
					$(item).css('left', 0 - (obj.max + x - p - o.offset) );
				}
			break;
			case 'top': 
				var p = parseInt($(item).css('top')) || 0;
				if(p <= 0-o.itemHeight){
					$(item).css('top', obj.max + x + p - o.offset);
				}
			break;
			case 'bottom':
				var p = parseInt($(item).css('top')) || 0;
				if(p >= o.height){
					$(item).css('top', 0 - (obj.max + x - p - o.offset) );
				}
			break;
		}
	},
	onEnd: function(obj, item){
		if(obj.items[obj.index] == item && $.isFunction(obj.options.onEnd)) obj.options.onEnd.apply(this,[obj, item]);
	},
	play: function(obj, delay){
		var delay =  delay || parseInt(obj.options.delay);
		obj.playing = true;
		clearTimeout(obj.timer);
		obj.timer = null;
		obj.timer = setTimeout(function(){$.jqCarousel.scrollImages(obj);}, delay);
	},
	stop: function(obj){
		clearTimeout(obj.timer);
		obj.timer = null;
		obj.playing = false;
	}
}

$.fn.jqCarousel = function(options){
	return this.each(function(i){
		var carousel = {
			options: $.jqCarousel.setOptions(options),
			element: $(this),
			wrapper: null,
			next: $('<div class="next" title="next">&raquo;</div>'),
			prev: $('<div class="prev" title="prev">&laquo;</div>'),
			items: [],
			timer: null,
			max: 0,
			playing: false, 
			scrollBy: 0,
			scrollAmount: 0,
			index: 0,
			direction: 'left',
			scrollDir: 1
		}
		$.jqCarousel.initVars(carousel);
		$.jqCarousel.initItems(carousel);
		$.jqCarousel.initEvents(carousel);
	});
}

$(function(){
	$('ul.carouselmenu').jqCarousel({
		onStart: highlight,
		onEnd: highlight,
		onScroll: delite,
		autoplay: true
	});
	
	function highlight(ui, item){
		var li = $('li', ui.element);
		$(li[ui.index]).addClass('active');
	}
	function delite(ui,item){
		$('li', ui.element).removeClass('active');
	}
});