


(function( $ ){

	var methods = {	
    
		// dFav Basic Functionality --------------------------------------------------------------------
		init : function( options ) {
            
			// Setting My Variables ----------------------------------------------------------------
			var settings = {
				parent : $(this),				// Unchanging, not a 'real' parameter
				item : 'li',					// What would you like to rotate? More often than not, this will be a LI
				nav : true,					// You want the navigation? Options: True, False, Custom
					navID : '',				// Nav ID. Used with custom Nav
					navPosition : 'before',			// Where you want your navigation? Options: Before, After
					navPrev : '',
					navNext : '',
					count : true,
					countContainer : '',
					currentCountContainer : '',
					totalCountContainer : '',
					playPause : false,
					playPauseID : '',
					creditsToggleID : '',
					creditsToggleTarget : '',
				transitionMove : 'group',			// How do you want items to move? Options: Group, Single
				transitionStyle : 'fade',			// Options: Slide, Fade
				transitionStart : 'auto',			// Options: Click, Auto
				transitionTime : 'fast',			// How quickly you want things to move about
				transitionDelay	: '2000'			// Only used with tStart of Auto. Sets how long we pause at each item.
			}	
			
			// ---------------------------------------------------------------------- END - Settings
			
			var n = 0;						// Counter Variable, NBD
			var itemsHeight = 0;					// Overall Height Variable
			
			// --------------------------------------------------------- END - Updating My Variables
			
			// Updating My Variables ---------------------------------------------------------------
			if ( options ) { 
				$.extend( settings, options );
			}
			// --------------------------------------------------------- END - Updating My Variables
			 
			// Init Operations ---------------------------------------------------------------------
			settings.navID = $(this).attr('id');
				
			if (settings.navID) {}
			
			// If we were not passed an ID'd object, get the class, and how many there are
			if (!settings.navID) { var selfClass = $(this).attr('class'); var selfLength = $('.' + selfClass).length; }
			// --------------------------------------------------------------- END - Init Operations
			
			// Functions ---------------------------------------------------------------------------
			
			// If our DOM object only has a class, add an ID
			assignID = function(pass) {
				
				if ( n < pass[2] ) {
					$('.' + pass[1]).eq(n).attr( 'id', pass[1] + '-' + (n+1) );
					settings.parent = $('#' + pass[1] + '-' + (n+1));
					n++;
				}
				
			}
			
			// Get all of the important information about the DOM object ---------------------------
			// Get, Create and save these variables for later --------------------------------------
			getData = function() {
			
				var parentID = settings.parent.attr('id');			// Get the ID of the parent DOM object
				var parentUL = settings.parent.find('ul');			// Find the UL inside of our DOM object, perhaps will be updated later with a supplied id of the UL
				var items = parentUL.find(settings.item);			// Find those pesky LI's
				var itemsCount = items.length;					// How many items are there?
				var itemsWidth = items.width();					// How wide are our items
				items.each(function(i) {					// Loop through items, looking for
					var testHeight = $(this).height();				// for the tallest
					if (testHeight > itemsHeight) {
						itemsHeight = testHeight;
					}    
			        });
				var itemsMargin = items.css('margin-right');			// What is the Right Margin
					itemsMargin = itemsMargin.split('px',1);		// Get rid of the measurement
					itemsMargin = parseInt(itemsMargin);			// Convert to an integer
					itemsWidth = itemsWidth + itemsMargin;			// Add to the width
				var itemsLength = items.length;					// How many items do we have?
				var parentWidth = parentUL.width();				// Width of the Parent Item, aka the DOM object
				var itemsOnScreen = Math.ceil( parentWidth / itemsWidth );	// Get Items on Screen
					// If Items on screen is equal to parent width, do some stuff
					if ( ( parentWidth == ( itemsOnScreen * itemsWidth ) ) && ( itemsOnScreen > 1) ) {
						itemsOnScreen--;				// Subtract from Items on Screent
						itemsWidth = ( Math.ceil( parentWidth / itemsOnScreen ) - ( itemsMargin / 2 ) );
						items.css({
							'width':itemsWidth + 'px',		// Set Item Width
							'margin-right':itemsMargin + 'px'	// Set Item Margin Right
						});
						itemsWidth = itemsWidth + itemsMargin;		// Update Item Width with new margin & width
					}
				var parentULWidth = itemsWidth * itemsCount;			// Get the width for the UL		
				var parentWrapID = parentID + '-wrap';				// Create the Wrap ID
				
				var itemsLeft = 0;
				var itemsRight = itemsCount - itemsOnScreen;
				var dItemsCount = itemsCount;
				var timer = 0;
				if ( settings.transitionMove == 'group' ) { dItemsCount = Math.ceil(itemsCount / itemsOnScreen); }
				
				// Navigational elements - Pretty self explanatory -----------------------------
				
				// If you are not using custom Nav, or you passed a classed DOM object
				if ( !settings.navID ) {
					settings.navID = parentID + '-slide-nav';
				}
				var prevID;
				if ( settings.navPrev ) { prevID = settings.navPrev; }
				if ( !settings.navPrev ) { prevID = parentID + '-slide-prev'; }
				var prevClass = 'prev-slide';
				var nextID;
				if ( settings.navNext ) { nextID = settings.navNext; }
				if ( !settings.navPrev ) { nextID = parentID + '-slide-next'; }
				var nextClass = 'next-slide';
				var currentCount = 1;
				var currentCountID;
				if ( settings.currentCountContainer ) { currentCountID = settings.currentCountContainer; }
				if ( !settings.currentCountContainer ) { currentCountID = parentID + '-slide-count'; }
				var currentCountClass = 'current-count';
				var totalCountID;
				if ( settings.totalCountContainer ) { totalCountID = settings.totalCountContainer; }
				if ( !settings.totalCountContainer ) { totalCountID = parentID + '-slide-total'; }
				var totalCountClass = 'total-count';
				var nav = '<ul id="'+settings.navID+'" class="slide-nav"><li><a href="#" id="'+prevID+'" class="'+prevClass+'">Previous</a></li><li class="nav-count-container"><span id="'+currentCountID+'" class="'+currentCountClass+'">'+currentCount+'</span> of <span id="'+totalCountID+'" class="'+totalCountClass+'">'+dItemsCount+'</span></li><li><a href="#" id="'+nextID+'" class="'+nextClass+'">Next</a></li></ul>';

				
			// Actions taken from gathered Data ----------------------------------------------------

			//Commented out the height setting on the parent element --  DC 09.29.11

				// Set some CSS and then wrap the whole thing 
				parentUL.css({
					'width':parentULWidth + 'px',			// Set width
					'height':itemsHeight + 'px',			// Set Height
					'position':'relative',				// Set position
					'top':0,					// You get it
					'left':0					// Ditto
				}).wrap('<div id="' + parentWrapID + '" style="width:' + parentWidth + 'px; overflow:hidden;height:'+(itemsHeight + 10)+'px" />'); 

				// Make a jQuery object out of our newly created DOM object
				var parentWrap = $('#' + parentWrapID );		// The Parent Trap, I mean Wrap
				
				// If you wanted navigation, we shall insert it now 
				if ( ( settings.nav ) && ( settings.nav != 'custom' ) ) {
					if ( settings.navPosition == 'before' ) {parentWrap.before(nav);}
					if ( settings.navPosition == 'after' ) {parentWrap.after(nav);}
				}

				if ( settings.nav == 'custom' ) {
					$('#' + currentCountID).text(currentCount);
					$('#' + totalCountID).text(dItemsCount);	
				}
				
				if ( settings.playPause && ( settings.transitionStart == 'auto' ) ) { $('#' + settings.playPauseID ).addClass('play'); }				

				// Make a jQuery object out of our newly created DOM object
				var prev = $('#' + prevID );				// Our Previous Button
				var next = $('#' + nextID );				// Our Next Button
				prev.addClass('inactive');
				
				// Placeholders for Calling Movement Variable
				var d;							// Direction
				var v;							// Variables
				var p;							// Placeholder
				var end = false; 					// Let's us know if we're at the end during looping
				
				var paused = true;
				var pause;
				
				// Create our data Object
				settings.parent.data({
					parentUL : parentUL,
					parentULWidth : parentULWidth,
					itemsWidth : itemsWidth,
					itemsHeight : itemsHeight,
					itemsOnScreen : itemsOnScreen,
					itemsLeft : itemsLeft,
					itemsRight : itemsRight,
					itemsCount : itemsCount,
					dItemsCount : dItemsCount,
					prev : prev,
					prevID : prevID,
					next : next,
					nextID : nextID,
					currentCount : currentCount,
					currentCountID : currentCountID,
					totalCountID : totalCountID,
					playPause : settings.playPause,
					playPauseID : settings.playPauseID,
					paused : paused,
					pause : pause,
					creditsToggleID : settings.creditsToggleID,
					creditsToggleTarget : settings.creditsToggleTarget,
					p : p,
					timer : timer,
					transitionStyle : settings.transitionStyle,
					item : settings.item,
					nav : settings.nav,
					navID : settings.navID,
					navPosition : settings.navPosition,
					transitionMove : settings.transitionMove,
					transitionStyle : settings.transitionStyle,
					transitionStart : settings.transitionStart,
					transitionTime : settings.transitionTime,
					transitionDelay	: settings.transitionDelay,
					count : settings.count,
					end : end
				});
				
				// Store our data Object
				v = settings.parent.data();
				
				
				// Set up Listeners -----------------------------------------------------------
				prev.click(function() { 
					d = 'prev'; 
					clearInterval(v.timer); 
					beginMove(v,d); 
					d = 'next'; 
					if ( v.transitionStart == 'auto' ) {
						v.timer = setInterval( function() { runTimer( v, d ); }, ( v.transitionDelay * 2 ) );
					}
					return false; 
				});
				
				next.click(function() { 
					d = 'next'; 
					clearInterval(v.timer); 
					beginMove(v,d); 
					if ( v.transitionStart == 'auto' ) {
						v.timer = setInterval( function() { runTimer( v, d ); }, ( v.transitionDelay * 2 ) );
					}
					return false; 
				}); 
				
				if ( ( v.transitionStart == 'auto' ) && ( !v.playPause ) ) {
					d = 'next'; 
					v.timer = setInterval( function() { runTimer( v, d ); }, v.transitionDelay );
				}
				
				if ( ( v.transitionStart == 'auto' ) && ( v.playPause ) && ( v.paused ) ) {
					$('#' + v.playPauseID).live('click', function() {
						d = 'next';
						$(this).removeClass('play').addClass('pause');
						v.pause = false;
						clearInterval( v.timer );
						v.timer = setInterval( function() { runTimer( v, d ); }, v.transitionDelay );
						return false;
					});
				}
				
				if ( v.playPause ) {
				
					$('#' + v.playPauseID + '.pause').live('click', function() {
						$(this).removeClass('pause').addClass('play');
						v.pause = true;
						clearInterval( v.timer );
						return false;
					});
					
					$('#' + v.creditsToggleID + ' p').click(function() { 
						$('.' + v.creditsToggleTarget).slideToggle(300); 
						$('#' + v.creditsToggleID + ' p').toggle();
						//return false;
					});
					
				}
				
			}
			
			// Move Function - v = Variables, d = Direction ----------------------------------------
			beginMove = function( v, d ) {

				if ( v.transitionMove == 'group' ) {
				
					if ( ( !v.end ) && ( v.itemsRight == 0 ) ) { v.end = true; }
					
					if ( ( d == 'next' ) && ( v.itemsRight > 0 ) ){
					
						if ( ( v.itemsRight > 0 ) && ( v.itemsRight <= v.itemsOnScreen ) ) {
							v.p = v.itemsRight;
							v.currentCount = v.dItemsCount;
							v.itemsLeft = (v.itemsCount - v.itemsOnScreen);
							v.itemsRight = 0;
							v.next.removeClass('inactive');
							v.prev.removeClass('inactive');
							move(v,d);
						}
						
						if ( v.itemsRight > v.itemsOnScreen ) { 
							v.p = v.itemsOnScreen;
							v.currentCount++;
							v.itemsLeft = (v.itemsLeft + v.itemsOnScreen);
							v.itemsRight = (v.itemsRight - v.itemsOnScreen);
							v.next.removeClass('inactive');
							v.prev.removeClass('inactive');
							move(v,d);
						}
												
					}
					if ( ( d == 'prev' ) && ( v.itemsLeft > 0 ) ) { 
						
						if ( ( v.itemsLeft > 0 ) && ( v.itemsLeft <= v.itemsOnScreen ) ) {
							v.p = v.itemsLeft;
							v.currentCount = 1;
							v.itemsLeft =  0;
							v.itemsRight = v.itemsCount - v.itemsOnScreen;
							v.prev.addClass('inactive');
							v.next.removeClass('inactive');
							move(v,d);
						}
						
						if ( v.itemsLeft > v.itemsOnScreen ) { 
							v.p = v.itemsOnScreen;
							v.currentCount--;
							v.itemsLeft = (v.itemsLeft - v.itemsOnScreen);
							v.itemsRight = (v.itemsRight + v.itemsOnScreen);
							v.prev.removeClass('inactive');
							v.next.addClass('inactive');
							move(v,d);
						}
						
					}
					
				}
				
				if ( v.transitionMove == 'single' ) {

					v.p = 1;					// Set multiplication variable to 1
					if ( ( d == 'next' ) && ( v.itemsRight > 0 ) ){
						v.currentCount++;
						v.itemsLeft++;
						v.itemsRight--;
						v.next.removeClass('inactive');
						v.prev.removeClass('inactive');
						move(v,d);
						updateCount(v);
					}
					if ( ( d == 'prev' ) && ( v.itemsLeft > 0 ) ){
						v.currentCount--;
						v.itemsLeft--;
						v.itemsRight++;
						v.next.removeClass('inactive');
						v.prev.removeClass('inactive');
						move(v,d);
						updateCount(v);
					}
					if ( ( d == 'next' ) && ( v.itemsRight == 0 ) && ( !v.end ) ) {
						clearInterval(v.timer);
						v.timer = setInterval( function() { v.end = true; }, v.transitionDelay );
					}
				}
				
				if ( v.end ) {		// only runs if user is on the last slide and clicks next
					if ( v.transitionStart == 'auto' ) { clearInterval( v.timer ); }
					d = 'next';
					v.currentCount = 1;
					v.itemsLeft =  0;
					v.itemsRight = v.itemsCount - v.itemsOnScreen;
					v.prev.addClass('inactive');
					v.next.removeClass('inactive');					
					if ( v.transitionStyle == 'slide' ) {
						// Move Schtuff around -----------------------------------------
						v.parentUL.animate({left: 0}, 'medium');
						updateCount(v);
					}
					if ( v.transitionStyle == 'fade' ) {
						// Move Schtuff around -----------------------------------------
						v.parentUL.fadeOut('fast').animate({left: 0}, 10).fadeIn('fast');
						updateCount(v);
					}
					v.end = false;
				}
				
				
			}
			// -------------------------------------------------------------------------- END - Move
			move = function(v,d) {
				v.end = false;
				if ( d == 'next' ) {
					if ( v.transitionStyle == 'slide' ) {
						// Move Schtuff around -----------------------------------------
						v.parentUL.animate({left: '-=' + ( v.itemsWidth * v.p )}, v.transitionSpeed);
						updateCount(v);
					}
					if ( v.transitionStyle == 'fade' ) {
						// Move Schtuff around -----------------------------------------
						v.parentUL.fadeOut('fast').animate({left: '-=' + ( v.itemsWidth * v.p )}, 10).fadeIn('fast');
						updateCount(v);
					}
				}
				if ( d == 'prev' ) {
					if ( v.transitionStyle == 'slide' ) {
						// Move Schtuff around -----------------------------------------
						v.parentUL.animate({left: '+=' + ( v.itemsWidth * v.p )}, v.transitionSpeed);updateCount(v);
					}
					if ( v.transitionStyle == 'fade' ) {
						// Move Schtuff around -----------------------------------------
						v.parentUL.fadeOut('fast').animate({left: '+=' + ( v.itemsWidth * v.p )}, 10).fadeIn('fast');
						updateCount(v);
					}
				}	
			}
			// Update Count - v = Variables --------------------------------------------------------
			updateCount = function( v ) { 

				if ( v.count ) {
					$('#' + v.currentCountID).text(v.currentCount);
					
					// Recalculate button states to prevent glitches
					if (v.currentCount == 1) { 			// if on first slide
						if (v.prev.hasClass('inactive')) {} else {v.prev.addClass('inactive');}
						v.next.removeClass('inactive');
					}
					else if (v.currentCount == v.dItemsCount) {	// if on last slide
						if (v.next.hasClass('inactive')) {} else {v.next.addClass('inactive');}
						v.prev.removeClass('inactive');
					}
					else {						// if neither first nor last slide
						v.next.removeClass('inactive');
						v.prev.removeClass('inactive');
					}
				} 
			}
			// ------------------------------------------------------------------ END - Update Count
		
			// Timer Function - v = Variables, d = Direction ---------------------------------------
			runTimer = function(v,d) {
			
				if ( !v.pause ) {
				
					v.paused = false;
					
					clearInterval( v.timer );
					if ( v.itemsRight == 0 ) {
						v.itemsLeft = 0; 
						v.itemsRight = (v.itemsCount - v.itemsOnScreen);
						v.currentCount = 1;
						v.prev.addClass('inactive');
						v.next.removeClass('inactive');
						if ( v.transitionStyle == 'slide' ) {
							// Move Schtuff around -----------------------------------------
							v.parentUL.animate({left: 0}, 'medium');
							updateCount(v);
						}
						if ( v.transitionStyle == 'fade' ) {
							// Move Schtuff around -----------------------------------------
							v.parentUL.fadeOut('fast').animate({left: 0}, 10).fadeIn('fast');
							updateCount(v);
						}
					}
					else { beginMove( v, d ); }
					v.timer = setInterval( function() { runTimer( v, d ); }, v.transitionDelay );
				
				}
				
				if ( v.pause ) { v.paused = true; clearInterval( v.timer ); }

				
			}
			// ---------------------------------------------------------------- END - Timer Function
			
			
			// --------------------------------------------------------------------- END - Functions
			
			// Each --------------------------------------------------------------------------------
			return this.each(function() {
			
				// Cache this
				var $this = $(this);
				
				if ( selfClass ) { var pass = [$this, selfClass, selfLength]; assignID(pass); }
				if ( settings.parent.find(settings.item).length > 1 ) {
					// If you weren't a blockhead and the plugin worked
					if ( settings.parent ) { getData(); }
					if ( !settings.parent ) { console.log("You didn't configure this correctly and didn't pass a live variable"); }
				}
				
				
			});
			// -------------------------------------------------------------------------- END - Each

		}	// -------------------------------------------------------------------------- END - Init

	};  // ----------------------------------------------------------------------------------- END - methods
		
$.fn.dSlides = function( method ) {

	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.dSlides' );
	}    

};

})( jQuery );
