(function($) {

	$.fn.ids_slider = function(options) {
		
		/* =================================== PUBLIC SETTINGS =================================== */
	
		var defaults = {
		
			imagesWrapper:			'slideshow-images',
			slideshowArrows:		'slideshow-arrows',
			speed:					600,
			interval:				1500,
			width:					0,
			height:					0,
			pause:					true,
			showIndicators: 		true,
			showArrows:				false,
			leftArrow:				'/plugin/examples/images/left-arrow.png',
			rightArrow:				'/plugin/examples/images/right-arrow.png',
			defaultIndicatorClass:	'default-indicator',
			currentIndicatorClass:	'current-indicator',
			indicatorPosition:		'-30px', // from the bottom of the slideshow container
			arrowPosition:			'10px',
			captions:				'false', // true | false 
		
		};
		
		/* =================================== PRIVATE SETTINGS =================================== */
		
		var private = {
		
			obj:					null,
			slides:					null,
			currentSlide: 			0,
			nextSlide:				1,
			indicatorCount:			0,
			timeOuts:				[],
			imgMaxWidth:			null,
			imgMaxHeight:			null,
			leftMostPosition:		null,
			reachedEnd:				false,
			amtToSlide:				null,
			pause:					false,
			captions:				[],
			
		}
		
		var methods = {
			
			init: function() {
	
				imgWidths = [];
				imgHeights = [];
	
				/* =================================== Get captions and remove them =================================== */
				
				if(options.captions == true) {
				
					private.obj.children('p').each(function() {
					
						private.captions.push(this.innerHTML);
					
					});
										
					private.obj.children('p').remove();
					
					private.obj.append('<div class="captions">'+private.captions[0]+'</div>');
					
				}
				
				private.obj.children('p').remove();
				
				
	
				/* ============================== Wrap .slideshow-images div around the images =================================== */
								
				imgStr = private.obj.html();
				private.obj.children('img').remove(); //remove copied images
				private.obj.append('<div class="'+options.imagesWrapper+'">'+imgStr+'</div>'); //add images back wrapped in slideshow-images div container
	
				/* =========================== Calculate the max width and height of the slideshow ======================== */
					
				var imgWidths = [];
				var imgHeights = [];
			
				/*$('.'+options.imagesWrapper+' img').each(function() {
					
					imgWidths.push($(this).width());
					imgHeights.push($(this).height());
				
				});
								
				methods.dimensions(imgWidths, imgHeights);
				*/
				
				private.slides			= $('.'+options.imagesWrapper+' img').size() - 1;
				private.imgMaxWidth 	= options.width;
				private.imgMaxHeight 	= options.height;
				
				
				private.obj.css({width: private.imgMaxWidth});
				
				/* =================================== Initialized inidicators and previous and next arrows =================================== */
												
				if(options.showIndicators) {
					methods.indicators();
				}
								
				if(options.showArrows) {
					methods.arrows();
				}
				
				/* =================================== Update css for slideshow container =================================== */
								
				private.obj.children('.'+options.imagesWrapper).css({position: 'relative', display:'block', height: private.imgMaxHeight+'px', zIndex: 0, width: private.imgMaxWidth+'px', 'overflow':'hidden'});
				
				/* Modify css for slideshow images */
				
				/* =================================== Update css for the actual slideshow images =================================== */
				
				private.obj.children('.'+options.imagesWrapper).children('img').each(function(i) {
		
					$(this).css({position: 'absolute', zIndex: 1, opacity: 1.0, top: 0, left: 0, display: 'none'});
				
				});
				
				/* =================================== Always display first slide =================================== */
				
				private.obj.children('.'+options.imagesWrapper).children('img:eq('+private.currentSlide+')').css({display: 'block', opacity: 1.0});
				
				/* =================================== Bind Events =================================== */
				
				methods.bind();
				
				
				/* =================================== Start Slideshow =================================== */
								
				private.timeOuts.push(setTimeout(function() {
					
					methods.start();
				
				}, options.interval));
					
			},
			
			/* =========== GET THE MAXIMUM WIDTH OF THE SLIDESHOW BY CHECKING THE WIDTH OF ALL IMAGES =============== */
	
			dimensions: function(widthArray, heightArray) {
				
				
				maxwidth = widthArray[0]
				maxheight = heightArray[0]
				
				private.slides = widthArray.length;
				
				for(i in widthArray) {
					
					if(widthArray[i] > maxwidth) {
						maxwidth = widthArray[i];
					}					
				}
				
				for(i in heightArray) {
					
					if(heightArray[i] > maxheight) {
						maxheight = heightArray[i];
					}					
				}
				
				private.imgMaxWidth = maxwidth;
				private.imgMaxHeight = maxheight;
								
			},
			
			indicators: function() {
				
				html = '<div class="slideshow-indicators">';
				
				for(i = 0; i < private.slides; i++) {
					
					html += '<div class="ids-indicator '+options.defaultIndicatorClass+'"></div>';
				}
			
				html += '</div>';
			
				$(private.obj).append(html);
				$('.slideshow-indicators').css({position:'absolute',  zIndex: 3,  bottom: options.indicatorPosition, cursor: 'pointer'});
				
				/* POSITION INDICATORS IN CENTER OF SLIDESHOW */
				
				indicatorWidth = $('.slideshow-indicators').width();
				$('.slideshow-indicators').css({width: indicatorWidth+'px', left: '50%', marginLeft: '-'+(indicatorWidth / 2)+'px'});
				
				//$('.'+this.defaultIndicatorClass+':eq(0)').removeClass(Slideshow.defaultIndicatorClass);
				$('.'+options.defaultIndicatorClass+':eq(0)').addClass(options.currentIndicatorClass);
				
			},
			
			arrows: function() {
	
				/* LEFT ARROW */
				
				html = '<img id="ids-previous" class="'+options.slideshowArrows+'" src="'+options.leftArrow+'" style="position: absolute; background-color: transparent; z-index: 3; cursor: pointer; top: '+(private.imgMaxHeight / 2)+'px; left:-25px;" alt="" />';
				
				$(private.obj).append(html);
				
				
				/* RIGHT ARROW */
			
				html = '<img id="ids-next" class="'+options.slideshowArrows+'" src="'+options.rightArrow+'" style="position: absolute; background-color: transparent; z-index: 3; cursor: pointer; top: '+(private.imgMaxHeight / 2)+'px; right:-25px;" alt="" />';
				
				$(private.obj).append(html);
			
			},
			
			bind: function() {
				
				/* =================================== If options.pause is true, enable pausing on mouse over and resuming on mouse out =================================== */
				
				if(options.pause == true) {
				
					/* Bind Pause Handler */
				
					private.obj.bind('mouseover', function() {
						
						methods.clearTimeouts();
						private.pause = true;
					
					});
					
					/* Bind Resume Handler */
					
					private.obj.bind('mouseout', function() {
					
						methods.clearTimeouts();
						private.pause = false;
						
						//$(this).css({'box-shadow': '0px 2px 3px #222'});
						
						private.timeOuts.push(setTimeout(function() {
						
							methods.start();
						
						}, options.interval));
					
					});
				
				}
				
				/* Bind Next Function */
				$('#ids-next').bind('click', function() {
				
					if ($(':animated').length) {
						return false;
    				}

					methods.next();
				
				});
				
				/* Bind Next Function */
				$('#ids-previous').bind('click', function() {
					
					if ($(':animated').length) {
						return false;
    				}
				
					methods.previous();
				
				});
				
				/* =================================== Bind gotoslide for indicator clicks =================================== */
		
				$('.ids-indicator').each(function(i) {
								
					$(this).click(function() {
						
						if ($(':animated').length) {
							return false;
    					}
						
						methods.gotoslide(i);	
					
					})
				
				});
		
			},
			
			unbind: function() {
				
				//private.obj.unbind('mouseover');
				//private.obj.unbind('mouseout');
				
				$('#ids-next, #ids-previous').unbind('click');
				$('.ids-indicator').unbind('click');
				
			},
			
			start: function() {
				
				/* ============================= IMPORTANT! NEED TO CHECK PAUSE VALUE ========================================== */
		
				if(options.pause == true && private.pause == true) {
					return;
				}
			
				 /* ========== IMPORTANT! NEED TO CHECK IF THERE IS A NEXT SLIDE, IF NOT, START OVER AGAIN ====================== */
				
				
				if(private.nextSlide == private.slides) {
					private.nextSlide = 0;
					private.reachedEnd = true;
				}
		
				/* PREPARE THE NEXT SLIDE */
				
				private.obj.children('.'+options.imagesWrapper).children('img:eq('+(private.nextSlide)+')').css({display: 'block', left: '-'+private.imgMaxWidth+'px', opacity: 1.0});
				
				/* PREPARE THE CURRENT SLIDE */
				
				private.obj.children('.'+options.imagesWrapper).children('img:eq('+private.currentSlide+')').css({display: 'block', opacity: 1.0});
			
				
				/* ANIMATE CURRENT SLIDE */
			
				private.obj.children('.'+options.imagesWrapper).children('img:eq('+private.currentSlide+')').stop().animate({
				    opacity: 1,
				    left: '+='+private.imgMaxWidth+'px',
				  }, options.speed, function() {
				
				    // Animation complete.
				    $(this).css({display: 'none'});
				  
				})
				
				/* ANIMATE NEXT SLIDE */
			
				
				private.currentSlide++;
				    
			    /* ====================== Update Indicators ========================== */ 
			    
			    $('.'+options.defaultIndicatorClass).removeClass(options.currentIndicatorClass);
			    
			    if(private.currentSlide == private.slides) {
			    	private.currentSlide = 0;
			    }
			    
				$('.'+options.defaultIndicatorClass+':eq('+private.currentSlide+')').addClass(options.currentIndicatorClass);
			
				private.obj.children('.'+options.imagesWrapper).children('img:eq('+(private.nextSlide)+')').stop().animate({
				    opacity: 1,
				    left: '+='+private.imgMaxWidth+'px',
				  }, options.speed, function() {
				
				    // Animation complete.
				    $(this).css({display: 'block'});
					
					/* ================ Increment currentSlide count ================== */
				    
				    private.nextSlide++;
									    
				    if(private.reachedEnd == true) {
				    	private.currentSlide = 0;
				    	private.nextSlide = 1;
				    	private.reachedEnd = false;
				    }
				    
					private.obj.children('.'+options.imagesWrapper).children('img').css({position: 'absolute', zIndex: 1, opacity: 1.0, top: 0, left: '0px', display: 'none'});
					private.obj.children('.'+options.imagesWrapper).children('img:eq('+private.currentSlide+')').css({position: 'absolute', zIndex: 1, opacity: 1.0, top: 0, left: '0px', display: 'block'});
				   				   
				    /* ================ Wait ... Animate next slide =================== */
				    
				   if(options.captions == true) {
				   		
				   		$('.captions').html(private.captions[private.currentSlide]);
				   
				   }
				    
				    private.timeOuts.push(setTimeout(function() {
				
						methods.start();
						
					}, options.interval));
				  
				})
			},
			
			
			next: function() {
					
				if(private.currentSlide == private.slides - 1) {
					methods.gotoslide(0);
				}
				else {
					methods.gotoslide(private.currentSlide + 1);
				}
				
			},
			
			previous: function() {
				if(private.currentSlide == 0) {
					methods.gotoslide(private.slides - 1);	
				}
				else {
					methods.gotoslide(private.currentSlide - 1);
				}
				
			},
			
			
			gotoslide: function(slide) {

				/* ===================== RETURN IF SLIDE CLICKED IS CURRENT SLIDE ========================= */	
								
				if(private.currentSlide == slide) {
					return;
				}
				
				methods.clearTimeouts();
				if(options.pause == true) {
					private.pause = true;
				}
								
				if(slide > private.currentSlide) {
					direction = 'right';
				} 
				
				else {
					direction = 'left';
				}
				
				positioning = private.imgMaxWidth;
				
				if(direction == 'right') {
										
					for(i = (private.currentSlide + 1) ; i <= slide; i++) {
					
						private.obj.children('.'+options.imagesWrapper).children('img:eq('+i+')').css({position: 'absolute', zIndex: 1, opacity: 1.0, top: 0, left: '-'+(positioning)+'px', display: 'block'});
						positioning+= private.imgMaxWidth;
					
					}
					
					private.nextSlide = private.currentSlide + 1;
				
				}
				
				else {
								
					for(i = (private.currentSlide - 1) ; i >= slide; i--) {
					
						private.obj.children('.'+options.imagesWrapper).children('img:eq('+i+')').css({position: 'absolute', zIndex: 1, opacity: 1.0, top: 0, left: (positioning)+'px', display: 'block'});
						positioning+= private.imgMaxWidth;
					
					}
					
					private.nextSlide = private.currentSlide - 1;	
					
				}
				
				if(direction == "right") {
					private.amtToSlide = private.obj.children('.'+options.imagesWrapper).children('img:eq('+(slide)+')').css('left').substring(1);
				}
				else {
					private.amtToSlide = private.obj.children('.'+options.imagesWrapper).children('img:eq('+(slide)+')').css('left');
				}
								
				/* ===================== PREPARE FOR ANIMATION ========================= */		
				
				imagesToAnimate = [];
				
				if(direction == 'right') {
				
					for(i = (private.currentSlide) ; i <= slide; i++) {
						
						imagesToAnimate.push( '.'+options.imagesWrapper+' img:eq('+i+')' );
						//imagesToAnimate.push(this.slideshow+' '+this.images+' img:eq('+i+')')
							
					}
					
				}
				
				else {
				
					for(i = (private.currentSlide) ; i >= slide; i--) {
						
						imagesToAnimate.push( '.'+options.imagesWrapper+' img:eq('+i+')' );
						
					}
				
				}
				
				animationString = imagesToAnimate.join(', ');
					
				/* ===================== BEGIN ANIMATION BETWEEN SLIDES ========================= */
						
				if(direction == 'right') {
				
					private.currentSlide = slide;
					private.nextSlide = slide + 1;
					
					/* ====================== Update Indicators ========================== */
					    
					    $('.'+options.defaultIndicatorClass).removeClass(options.currentIndicatorClass);
						$('.'+options.defaultIndicatorClass+':eq('+private.currentSlide+')').addClass(options.currentIndicatorClass);
								
					$(animationString).stop().animate({
					    left: '+='+private.amtToSlide,
					  }, options.speed, function() {
					
					    // Animation complete.												
						methods.clearTimeouts();
						
						if(options.captions == true) {
							
							$('.captions').html(private.captions[private.currentSlide]);
							
						}
							
						private.timeOuts.push(setTimeout(function() {
					
							methods.start();
						
						}, options.interval));
						
					});
				
				}
				
				else {
						
					private.currentSlide = slide;
					private.nextSlide = slide + 1;
					
					/* ====================== Update Indicators ========================== */
					    
					    $('.'+options.defaultIndicatorClass).removeClass(options.currentIndicatorClass);
						$('.'+options.defaultIndicatorClass+':eq('+private.currentSlide+')').addClass(options.currentIndicatorClass);
								
					$(animationString).stop().animate({
					    left: '-='+private.amtToSlide,
					  }, options.speed, function() {
					
					    // Animation complete.
												
						methods.clearTimeouts();
						
						if(options.captions == true) {
							
							$('.captions').html(private.captions[private.currentSlide]);
							
						}
						
						private.timeOuts.push(setTimeout(function() {
					
							methods.start();
						
						}, options.interval));
						
					});
				
				}
				
			},
			
			clearTimeouts: function() {
		
				for(key in private.timeOuts ){
			    	clearTimeout(private.timeOuts[key]);  
			  	}
			  
			  	private.timeOuts = [];
			}
			
			
		} //end methods object
		
		var options = $.extend(defaults, options);
		
		return this.each(function() {
			
			private.obj = $(this);
			methods.init();
			
		});
		
	};

})(jQuery);
