(function( $ ){
	var methods = {
		init: function( options ) {
			return this.each(function(){
				var settings = {
					distance: 'auto',				// between items
					items_visible: 1,				//number of visible
					speed: 1000,					// animation speed
					interval: 5000,					// ms between each slide
					item_jq: '.item',				// jquery-string of items
					autostart: true,				// autostart sliding after init
					takeShortcut: true,				// take shortest direction
					afterInit: function(data) {},	// after init, just before start ( if autostart )
					itemChanged: function(data) {},	// after animation, index is changed. Use data.currentItem and data.previousItem
					startItem: 0					// set current item for init. 0-based
				};
				// if options exist, lets merge them with our default settings
				if ( options ) { 
					$.extend( settings, options );
				}

				var $this = $(this);
				var data = methods.getData.call( $this, true );
				if ( !data ) {
					data = {
						target : $this,				// jquery-object of slider
						settings: settings,			// save extended settings
						itemCount: 0,				// number of items in slider
						previousItem: 0,			// number of first visible item just before animation stopped
						currentItem: settings.startItem,  // number of first current visible item
						running: false				// state of slider
					};
					$this.data('rexslider', data);
				}

				if ( data.settings.distance == 'auto' ) {
					data.settings.distance = $this.find( data.settings.item_jq+':first').outerWidth();
				}

				data.itemCount = $this.find( data.settings.item_jq).length;
				
				// set elements to correct position
				$this.find( data.settings.item_jq).each(function(i,el) {
					$(el).css({ left: ((  i - data.currentItem + data.itemCount) % data.itemCount ) * data.settings.distance });
				});
				
				data.enable =  data.itemCount > data.settings.items_visible;
				data.settings.afterInit.call( this, data );
				if ( data.enable && data.settings.autostart ) {
					methods.start.call( $this );
				}
			});
		},
		getData: function( noinit ) {
			var data = this.data('rexslider');
			// If the plugin hasn't been initialized yet
			if ( !data && !noinit ) {
				methods.init.call(this);
				var data = this.data('rexslider');
			}
			return data;
		},
		destroy: function( ) {
			return this.each(function(){
				$(this).removeData('rexslider');
			});
		},
		start: function() {
			var data = methods.getData.call(this);
			if ( !data.running ) {
				data.running = true;
				methods.slide.call(this,1,true);
			}
			return this;
		},
		stop: function() {
			var data = methods.getData.call(this);
			data.running = false;
			if ( data.waiting ) {
				clearTimeout( data.waiting );
				data.waiting = null;
				$(this).find(data.settings.item_jq).stop(true,true);
			}
			return this;
		},
		slide: function( steps, delay ) {
			var dir = steps > 0 ? 1 : -1;
			var data = methods.getData.call( this );
			var $this = this;
			var target = data.target;
			if ( data.waiting ) {
				clearTimeout( data.waiting );
				data.waiting = null;
				$this.find(data.settings.item_jq).stop(true,true);
			}
			if ( delay ) {
				data.waiting = setTimeout( function() { methods.slide.call(target,steps); }, data.settings.interval );
				return;
			}
			$this.find(data.settings.item_jq).each(function(i) {
				$(this)
					.queue(function(){
						data.waiting = false;
						var left = $(this).position().left;
						$(this).css({ left: ((  i - data.currentItem + (dir > 0 ? 0 : 1) + data.itemCount)% data.itemCount - (dir > 0 ? 0 : 1)) * data.settings.distance });
						$(this).dequeue();
					})
					.animate(
						{ left: (dir<0 ? '+=' : '-=' )+data.settings.distance },
						data.settings.speed
					)
					.queue(function() {
						if ( i==0 ) {
							data.previousItem = data.currentItem;
							data.currentItem = ( data.currentItem + dir + data.itemCount ) % data.itemCount;
							data.settings.itemChanged.call( $this, data );
							if ( data.running ) {
								steps -= dir;
								if ( steps ) {
									methods.slide.call(target, steps );
								} else {
									methods.slide.call(target, 1, true );
								}
							}
						}
						$(this).dequeue();
					});
			});
			return this;
		},
		slideTo: function( index ) {
			var data = methods.getData.call(this);
			if ( data.waiting ) {
				clearTimeout( data.waiting );
				data.waiting = null;
				this.find(data.settings.item_jq).clearQueue();
			}
			var steps = ( index-data.currentItem+data.itemCount ) % data.itemCount;
			if ( data.settings.takeShortcut && data.itemCount - steps < steps ) steps -= data.itemCount;
			if ( steps != 0 ) methods.slide.call(data.target, steps );
			return this;
		}
	};

	$.fn.rexslider = function( method ) {
		// Method calling logic
		if ( methods[method] ) {
			return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
		} else if ( typeof method === 'object' || ! method ) {
			return methods.init.apply( this, arguments );
		} else {
			$.error( 'Method ' + method + ' does not exist on jQuery.rexslider' );
			return this;
		}
	};
})( jQuery );

