(function($) {
	
	$.fn.lemFlow = function(settings) {
		var config = {
			prev: '.prev',				// The element that will trigger the moveToPrev action
			next: '.next',				// The element that will trigger the moveToNext action
			width: 200,					// The width in pixels of a single element
			numVisible: 1,			// The number of visible elements at a time
			height: 0,					// (optional) The height value in pixels of the holder and tray
			current: '',					// (optional) The element that will display the current position -- ex: '.current'
			total: '',						// (optional) The element that will display the total number of elements -- ex: '.total'
			duration: 300,  			// (optional) A string ('slow' or 'fast) or number (milliseconds) determining how long the animation will run.
			easing: null, 				// (optional) A string indicating which easing function to use for the transition.
			pos: 1,							// (optional) The starting position
			loop: false,					// (optional) If true, the flow will loop when it reaches the end
			linkset: ''						// (optional) A class of links that calls a specific element
		};
		
		if (settings) $.extend(config, settings);
		
		var mThis = this;			//This
		var holder;						//The div that's holding the elements
		var elements;					//The elements in the Holder
		var numElements;			//The number of elements in the Holder
		var tray;							//The tray that will be used to move the elements
		var moving;					//If true, the tray is currently moving
		
		/* ------ INIT ------------------------------------------------------------------------ */
		var init = function(){
			config.pos -= 1;
			holder = '#'+$(mThis).attr('id');
			elements = $(holder).children();
			numElements = elements.length;
			tray = holder+"Tray";
			moving = false;
			$(config.prev).click(moveToPrev);
			$(config.next).click(moveToNext);
			if(config.linkset != ''){
				$(config.linkset).click(moveToSpecific);
			}
			
		}
		/* --------------------------------------------------------------------------------------- */
		
		/* ------ WRITE TOTAL -------------------------------------------------------- */
		var writeTotal = function(){
			
			if(config.total != ''){
				$(config.total).html(numElements);
			}
			
		}
		/* --------------------------------------------------------------------------------------- */
		
		/* ------ MANIPULATE ELEMENTS -------------------------------------- */
		var manipulateElements = function(){
			
			for(var i = 0; i < elements.length; i++){
				elements.eq(i).css('float','left');
			}
			
		}
		/* --------------------------------------------------------------------------------------- */
		
		/* ------ MANIPULATE HOLDERS ---------------------------------------- */
		var manipulateHolders = function(){
			
			if(config.loop){
				for(var i = 0; i < config.numVisible; i++){
					elements.eq(i).clone().appendTo(holder);
				}
			}
			$(holder).children().wrapAll("<div id=\""+tray.substring(1)+"\">");
			$(holder).css('overflow','hidden');
			$(holder).css('position','relative');
			
		}
		/* --------------------------------------------------------------------------------------- */
		
		/* ------ MANIPULATE TRAY ----------------------------------------------- */
		var manipulateTray = function(){
			
			$(tray).append("<div style=\"clear:both;\"></div>");
			$(tray).css('position','relative');
			$(tray).css('right','0');
			if(config.loop){
				$(tray).css('width',config.width*(numElements+config.numVisible)+'px');
			} else {
				$(tray).css('width',config.width*numElements+'px');
			}
			makeSelected(config.pos);
			teleport(config.pos);
			
		}
		/* --------------------------------------------------------------------------------------- */
		
		/* ------ SET HEIGHT ------------------------------------------- */
		var setHeight = function(){
			
			var height;
			
			if(config.height != 0){
				
				height = config.height;
				
				$(holder).css('height',height+'px');
				$(tray).css('height',height+'px');
				
			}
						
		}
		/* --------------------------------------------------------------------------------------- */
		
		/* ------ MOVE TRAY ----------------------------------------------------------- */
		var moveTray = function(){
			
			$(tray).animate({
				right: config.width*config.pos+"px"
			}, config.duration,config.easing,function(){
				
				if(config.loop && config.pos == numElements){
					teleport(0);
				} else if(config.current != '') {
					$(config.current).html(config.pos+1);
				}
				
				moving = false;
				
			});
		
		}
		/* --------------------------------------------------------------------------------------- */
		
		/* ------ TELEPORT ------------------------------------------------------------- */
		var teleport = function(target){
			
			config.pos = target;
			$(tray).css('right', config.width*config.pos+"px");
			
			if(config.current != '' && config.pos != numElements){
				$(config.current).html(config.pos+1);
			}
			
		}
		/* --------------------------------------------------------------------------------------- */
		
		/* ------ MOVE TO PREV ----------------------------------------------------- */
		var moveToPrev = function(){
		
			if(!moving){
				
				moving = true;
				
				if(config.pos > 0){
					config.pos -= 1;
				} else if(config.loop && config){
					teleport(numElements);
					config.pos = numElements-1;
				} else {
					config.pos = numElements-(1*config.numVisible);
				}
				
				makeSelected(config.pos);
				moveTray();
				
			}
			
			return false;
		}
		/* --------------------------------------------------------------------------------------- */
		
		/* ------ MOVE TO NEXT -------------------------------------------------------- */
		var moveToNext = function(){
		
			var limit;
			
			if(!moving){
				
				moving = true;
				
				if(config.loop){
					limit = numElements;
				} else {
					limit = numElements-config.numVisible;
				}
				
				if(config.pos < limit){
					config.pos += 1;
				} else {
					config.pos = 0;
				}
				
				//In a case of loop, to have the right element selected when going back to the first...
				var target = config.pos;
				if(target == numElements){
					target = 0;
				}
				
				makeSelected(target);
				moveTray();
			
			}
			
			return false;
			
		}
		/* --------------------------------------------------------------------------------------- */
		
		/* ------ MOVE TO SPECIFIC ----------------------------------------------------- */
		var moveToSpecific = function(){
			
			if(!moving){
				
				moving = true;
				
				var target = $(this).attr('rel') - 1;
				
				makeSelected(target);
				
				if(target > numElements-(1*config.numVisible)){
					target = numElements-(1*config.numVisible);
				}
				
				config.pos = target;
								
				moveTray();
				
			}
			
			return false;
		}
		/* --------------------------------------------------------------------------------------- */
		
		/* ------ MAKE SELECTED ----------------------------------------------------- */
		var makeSelected = function(target){
			
			$(config.linkset).removeClass('lemSelected');
			
			if(config.linkset != ''){
				$(config.linkset).eq(target).addClass('lemSelected');
			}
						
			return false;
		}
		/* --------------------------------------------------------------------------------------- */
		
		
		init();
		writeTotal();
		manipulateElements();
		manipulateHolders();
		manipulateTray();
		setHeight();
		
		return this;
		
	};
	
})(jQuery);
