
(function( $ ){
	$.fn.wsImageSlider = function(options) {
		
		var settings = {
			
			orientation : "horizontal",
			
			slideSelector : ".slide",
			slidePositionSelector : ".slidePositioner",
			nextSelector : ".slideNext",
			prevSelector : ".slidePrev",
			slideButtonInactive : "inactive",
			extraInfoSelector : ".fadeHide",
			
			inactiveSlideMarker : "inactiveSlide",
			activeSlideMarker : "activeSlide",
			
			showRandom : 0,
			transitionTime : 300,
			showItems : 3,
			useFade : true,
			fadeInactive : 40,
			fadeActive : 100,
			
			offsetX : 0,
			offsetY : 0,
			
			autoMargin : true,
			marginLeft : 0,
			marginRight : 0,
			marginTop : 0,
			marginBottom : 0,
			forceEntryHeight : 0,
			
			allowExtremities : false,
			lowerLimit : 1,
			upperLimit : 1
			
		};
		
		var maxWidth = 0, maxHeight = 0, selectedItem = 0, totalItems = 0;
		
		var methods = {
			
			init : function() {
			
				totalItems = $(this).find(settings.slideSelector).length;
				
				$(this).find(settings.slideSelector).each(function(){
					$(this).addClass(settings.inactiveSlideMarker);
					
					maxWidth  = Math.max( maxWidth, $(this).width() );
					maxHeight = Math.max( maxHeight, $(this).height() );
					
					// Set all "image holders" to the exact width and height of their image
					$(this).find(".imageHolder").css({
						height : $(this).find("img.mainImage").attr("height"),
						width : $(this).find("img.mainImage").attr("width")
					});
					
					
				}).width(maxWidth);
				
				if (settings.forceEntryHeight) {
					$(this).find(settings.slideSelector).height(settings.forceEntryHeight);
					maxHeight = settings.forceEntryHeight;
				} else {
					$(this).find(settings.slideSelector).height(maxHeight);
				}
				
				
				if (settings.allowExtremities) {
					settings.lowerLimit = 1;
					settings.upperLimit = totalItems;
				} else {
					settings.lowerLimit = 2;
					settings.upperLimit = totalItems - 1;
				}
				
				
				//maxHeight = $(this).find(settings.slidePositionSelector).height();
				
				// If fading is used, fade the inactive slides now
				if (settings.useFade) $(this).find(settings.slideSelector).fadeTo(0, (settings.fadeInactive / 100));
				
				var margin = methods.recalculateMargins.call(this, true);
				
				if (settings.orientation == "horizontal") {
					$(this).height(maxHeight).find(".slideContainer").height(maxHeight);
				}
				
				if (settings.showRandom) {
					selectedItem = Math.ceil(totalItems * Math.random()); 
				} else {
					//selectedItem = (totalItems > 1) ? Math.ceil(totalItems / 2) : settings.lowerLimit;
					selectedItem = settings.lowerLimit;
				};
				
				$(this).find(settings.slidePositionSelector + " " + settings.extraInfoSelector).hide();
				
				if (settings.orientation == "horizontal") {
					var centerPoint = Math.floor($(this).width() / 2);
				} else {
					var centerPoint = Math.floor($(this).height() / 2);
				}
				
				$(this).find(settings.nextSelector).click( methods.nextItem ).hover( function(){ jQuery(this).addClass("hover"); }, function(){ jQuery(this).removeClass("hover"); });
				$(this).find(settings.prevSelector).click( methods.prevItem ).hover( function(){ jQuery(this).addClass("hover"); }, function(){ jQuery(this).removeClass("hover"); });
				
				$(this).addClass("wsISinstance");
				
				$(this).data("wsIS", {
					settings : settings,
					selectedItem : selectedItem,
					oldItem : 0,
					totalItems : totalItems,
					centerPoint : centerPoint,
					margin : margin,
					maxWidth : maxWidth,
					maxHeight : maxHeight
				});
				
				methods.showSelectedItem.call(this, true)
				
			},
			
			recalculateMargins : function() {
				var margin;
				if ( settings.autoMargin ) {
					if (settings.orientation == "horizontal") {
						margin = ($(this).width() - (settings.showItems * maxWidth) );
					} else {
						margin = ($(this).height() - (settings.showItems * maxHeight) );
					}
					if (settings.showItems > 1) margin /= settings.showItems;
					margin = Math.floor(margin);
					var halfMargin = Math.floor(margin/2);
					
					if (settings.orientation == "horizontal") {
						$(this).find(settings.slideSelector).css({"margin-right" : halfMargin + "px", "margin-left" : halfMargin + "px"});
					} else {
						$(this).find(settings.slideSelector).css({"margin-top" : halfMargin + "px", "margin-bottom" : halfMargin + "px"});
					}
				} else {
					if (settings.orientation == "horizontal") {
						margin = settings.marginLeft + settings.marginRight;
						$(this).find(settings.slideSelector).css({"margin-right" : settings.marginRight + "px", "margin-left" : settings.marginLeft + "px"});
					} else {
						margin = settings.marginTop + settings.marginBottom;
						$(this).find(settings.slideSelector).css({"margin-top" : settings.marginTop + "px", "margin-bottom" : settings.marginBottom + "px"});
					}
				}
				
				// Force slide container to be very wide (or tall), so it can contain all entries
				if (settings.orientation == "horizontal") {
					$(this).find(settings.slidePositionSelector).width( totalItems * (maxWidth + margin) );
				} else {
					$(this).find(settings.slidePositionSelector).height( totalItems * (maxHeight + margin) );
				}
				
				return margin;
				
			},
			
			
			
			showSelectedItem : function(noAnimation, noOldMark) {
				var objData = $(this).data("wsIS");
				
				// Calculate new position
				var dirToUse = (settings.orientation == "horizontal" ? objData.maxWidth : objData.maxHeight);
				var offsetToUse = (settings.orientation == "horizontal" ? settings.offsetX : settings.offsetY);
				var newPos = objData.centerPoint - ((objData.selectedItem - 1) * (dirToUse + objData.margin)) - Math.floor(dirToUse / 2) - Math.ceil(objData.margin / 2) + offsetToUse;
				
				$(this).stop(1,1).find("*").stop(1,1);
				
				if (noAnimation) {
					$(this).find(objData.settings.slidePositionSelector).css((settings.orientation == "horizontal" ? "left" : "top"), newPos + "px");
					if (objData.useFade) {
						$(this).find(objData.settings.slideSelector).eq(objData.selectedItem - 1).fadeTo(0, objData.settings.fadeActive).find(objData.settings.extraInfoSelector).show(0);
						if (objData.oldItem && !noOldMark) {
							$(this).find(objData.settings.slideSelector).eq(objData.oldItem - 1).fadeTo(0, objData.settings.fadeInactive).find(objData.settings.extraInfoSelector).hide(0);
						};
					}
				} else {
					var parObj = $(this);
					
					if (objData.settings.useFade) {
						$(this).find(objData.settings.slideSelector).eq(objData.selectedItem - 1)
							.fadeTo(objData.settings.transitionTime, objData.settings.fadeActive / 100)
							.find(objData.settings.extraInfoSelector)
							.fadeIn(objData.settings.transitionTime);
						if (objData.oldItem && !noOldMark) {
							$(this).find(objData.settings.slideSelector).eq(objData.oldItem - 1)
								.fadeTo(objData.settings.transitionTime, objData.settings.fadeInactive / 100)
								.find(objData.settings.extraInfoSelector)
								.fadeOut(objData.settings.transitionTime);
						};
					} else {
						$(this).find(objData.settings.slideSelector).eq(objData.selectedItem - 1).find(objData.settings.extraInfoSelector).show();
						if (objData.oldItem && !noOldMark) {
							$(this).find(objData.settings.slideSelector).eq(objData.oldItem - 1).find(objData.settings.extraInfoSelector).hide();
						};
					};
					
					
					var animProperties = {};
					animProperties[(settings.orientation == "horizontal" ? "left" : "top")] = newPos + "px";
					
					$(this).find(objData.settings.slidePositionSelector).animate( animProperties, objData.settings.transitionTime);
				};
				
				$(this).find(objData.settings.slideSelector).eq(objData.selectedItem - 1).removeClass(settings.inactiveSlideMarker).addClass(settings.activeSlideMarker);
				if (objData.oldItem && !noOldMark) {
					$(this).find(objData.settings.slideSelector).eq(objData.oldItem - 1).removeClass(settings.activeSlideMarker).addClass(settings.inactiveSlideMarker);
				};
				
				if (!noOldMark) {
					objData.oldItem = objData.selectedItem;
					$(this).data("wsIS", objData);
				};
				
				if (objData.selectedItem > settings.lowerLimit) {
					$(this).find(objData.settings.prevSelector).removeClass(objData.settings.slideButtonInactive);
				} else {
					$(this).find(objData.settings.prevSelector).addClass(objData.settings.slideButtonInactive);
				};
				
				if (objData.selectedItem < settings.upperLimit) {
					$(this).find(objData.settings.nextSelector).removeClass(objData.settings.slideButtonInactive);
				} else {
					$(this).find(objData.settings.nextSelector).addClass(objData.settings.slideButtonInactive);
				};
			},
			
			nextItem : function() {
				$(this).blur();
				var instance = $(this).parents(".wsISinstance:first");
				var objData = instance.data("wsIS");
				if (objData.selectedItem < settings.upperLimit) {
					objData.selectedItem += 1;
					instance.data("wsIS", objData);
					methods.showSelectedItem.call(instance);
				};
			},
			
			prevItem : function() {
				$(this).blur();
				var instance = $(this).parents(".wsISinstance:first");
				var objData = instance.data("wsIS");
				if (objData.selectedItem > settings.lowerLimit) {
					objData.selectedItem -= 1;
					instance.data("wsIS", objData);
					methods.showSelectedItem.call(instance);
				};
			},
			
			windowResize : function(e) {
				
				var parent = e.data.parent;
				if (typeof(parent) === 'object') {
					var margin = methods.recalculateMargins.call(parent, false);
					var centerPoint = Math.floor($(parent).width() / 2);
					
					var objData = $(parent).data("wsIS");
					objData.margin = margin;
					objData.centerPoint = centerPoint;
					$(parent).data("wsIS", objData);
					
					methods.showSelectedItem.call(parent, true, true);
				};
			}
			
		};
		

		return this.each(function() {
			if (options) {
				$.extend( settings, options );
			};
			
			//$(window).bind('resize.wsimageslider', {parent: this}, methods.windowResize );
			
			methods.init.call(this);
		});

	};
})( jQuery );

