(function($) {
	var t = $.tools.scrollable; 
	t.plugins = t.plugins || {};
	t.plugins.circular = {
		version: '0.5.1', 
		conf: { 
			api: false,
			clonedClass: 'cloned'
		} 		
	};
	$.fn.circular = function(opts)  {
		var config = $.extend({}, t.plugins.circular.conf), ret;
		$.extend(config, opts);
		this.each(function() {			
			var api = $(this).scrollable(),
				 items = api.getItems(), 
				 conf = api.getConf(), 
				 wrap = api.getItemWrap(), 
				 index = 0;
			if (api) { ret = api; }
			if (items.length < conf.size) { return false; }
			items.slice(0, conf.size).each(function(i) {
  				$(this).clone().appendTo(wrap).click(function()  {
					api.click(items.length + i);
					
				}).addClass(config.clonedClass);			
			});			
			var tail = $.makeArray(items.slice(-conf.size)).reverse();
  			$(tail).each(function(i) {
				$(this).clone().prependTo(wrap).click(function()  {
					api.click(-i -1);			
					
				}).addClass(config.clonedClass);				
			});
			var allItems = wrap.children(conf.item);
			var hc = conf.hoverClass;
			if (hc) {
				allItems.hover(function()  {
					$(this).addClass(hc);		
				}, function() {
					$(this).removeClass(hc);	
				});						
			}
			function seek(i) {
				var item = allItems.eq(i);
				if (conf.vertical) {						
					wrap.css({top: -item.position().top});
				} else {
					wrap.css({left: -item.position().left});							
				}					
			}
			seek(conf.size);			
			$.extend(api, {
				move: function(offset, time, fn, click) {  
					var to = index + offset + conf.size;				
					var exceed = to > api.getSize() - conf.size; 
					if (to <= 0 || exceed) {
						var fix = index + conf.size + (exceed ? -items.length : items.length);
						seek(fix);
						to = fix + offset;
					} 
					if (click) {
						allItems.removeClass(conf.activeClass)
							.eq(to + Math.floor(conf.size / 2)).addClass(conf.activeClass);
					}
					if (to === index + conf.size) { return self; }					
					return api.seekTo(to, time, fn);
				},			
				begin: function(time, fn) {
					return this.seekTo(conf.size, time, fn);	
				},
				end: function(time, fn) {				
					return this.seekTo(items.length, time, fn);	
				},
				click: function(i, time, fn) {		
					if (!conf.clickable) { return self; }
					if (conf.size == 1) { return this.next(); }
					var to = i - index, klass = conf.activeClass;				
					to -= Math.floor(conf.size / 2);				
					return this.move(to, time, fn, true);
				},
				getIndex: function() {
					return index;  
				},
				setPage: function(page, time, fn) {
					return this.seekTo(page * conf.size + conf.size, time, fn);	
				},
				getPageAmount: function()  {
					return Math.ceil(items.length / conf.size);		
				},
				getPageIndex: function()  {            	
					if (index < 0) { return this.getPageAmount() -1; }
					if (index >= items.length) { return 0; }
					var i = (index + conf.size) / conf.size -1;
					return i;
				},
				getVisibleItems: function() {
					var i = index + conf.size;
					return allItems.slice(i, i + conf.size);	
				} 
			});  
			api.onStart(function(e, i) {		
				index = i - conf.size;
				return false;
			});				
			api.getNaviButtons().removeClass(conf.disabledClass);
		});
		return config.api ? ret : this;
	};
})(jQuery);
