/*

	jQuery.Slider 4
	
	------------------------------------------------------------------------------------------------------------------------------------------------------
	
	Notes for version 2.1
	
	ROGERIO - 16.06.201 
	--------------------------------------------------------------------------------
	
	***
	
	When implementing script on body.com.au the direction of the slide was buggy and the slider was automatically sliding all the way back to the beginnning
	when the last slide was reached and the next button clicked. In order to fix the issue the conditional statements in the click events in the next and previous buttons
	were altered to use the following functions:
	
	isCurrentFirstMarker()
	isCurrentLastMarker()
	
	These functions provide a more efficient way of detecting when the first and last marked panels have been reached, therefore the slider does not slide automatically anymore.'
	
	P.S.: The implementation for single sliding panels must be tested with this change in order to ensure the script works as expected.
	
	***
	
	The move() method has been added to the api and it will allow for sliding programatically when passing the position to move to as a literal object.
	
	e.g.: {panel:0}   P.S.: The position starts at index 0.
	
	***
	
	Notes for version 4
	
	ROGERIO - 23.08.201 
	--------------------------------------------------------------------------------
	
	Add the property 'sliderOverflow' used to set the overflow rule for the slider itself. This is useful for scenarions 
	when the panels are to be visible when outside the targeted viewable area
	
	The slider was updated to use negative margins as opposed to scrolling in order to avoid the overflow blug which occurs with the jQuery animation
	
	The reposition method was added to the api
	
	
	Notes for version 4.1
	
	ROGERIO - 09.09.201 
	--------------------------------------------------------------------------------
	
	

*/

(function( $ ) {
	
$.fn.Slider = function(options){
	
// ---------------------------------------------------------------------------------------	START	- 	SETTINGS

	var o = $.extend({
	
		orientation: 'horizontal', 		// horizontal and vertical
		resizable: true,
		panelsNum: 1,
		continuous: true,
		repeatable: true,
		reversible: true,
		interval: 2000,
		duration: 350,
		durationFraction: 1,
		effect: 'swing',
		playOrder: 'ascending',			//ascending and descending
		
		holderQuery: '.holder',
		panelsQuery: '.panels',
		panelWidthCalculation: null,
		repeatItemClass: 'its-a-repeat',
		panelMarkerClass: 'marker',
		
		sliderOverflow: false,
		
		hasAnchors: false,
		anchorsQuery: '.slider-nav a',
		preventAnchorsDefault: true,
		anchorsEvent: 'click',
		anchorsCurrentClass: 'current',
		
		hasPrevNext: false,
		prevQuery: '.previous',
		nextQuery: '.next',
		preventPrevNextDefault: true,
		
		hasPlayPause: false,
		playPauseQuery: '.play-pause',
		preventPlayPauseDefault: true,
		playPauseEvent: 'click',
		
		selectedClass: 'selected',
		
		afterInitialized: function(){},
		
		onPlay: function(){},
		onPause: function(){},
		beforeMove: function(){},
		afterMove: function(){}
			
	},options);
	
	if(o.panelsNum !== 1)
	{
		o.repeatable = false;	
	}
	
	
	
// ---------------------------------------------------------------------------------------	END		-	SETTINGS			
	
// ---------------------------------------------------------------------------------------	START	-	PRIVATE PROPERTIES

	var $slider = null;
	var $holder = null;
	var $panels = null;
	var $markedPanels = null;
	var $anchors = null;
	
	var hasDummy = false;
	
	var interval = null;
	


// ---------------------------------------------------------------------------------------	END		-	PRIVATE PROPERTIES

// ---------------------------------------------------------------------------------------	START	-	PRIVATE METHODS

	function setUp()// Sets position of panels
	{
		var holderStripDim = 0;
		
	//--Set up the position of each panel
		$panels.each(function($key,$value){
			var $e = $(this);
			$e.css({float:'left'}).attr('rel',holderStripDim);
			holderStripDim += (o.orientation == 'horizontal') ? $e.innerWidth() : $e.innerHeight();
		});	
		
	//--Set up slider and holder
		if(o.orientation === 'horizontal')
		{
			$holder.css({
				width: holderStripDim,
				height: $panels.eq(0).innerHeight()
			});
		
			$slider.css({
				width: ($panels.eq(0).innerWidth() * o.panelsNum),
				height: $panels.eq(0).innerHeight(),
				overflow: (o.sliderOverflow) ? 'visible' : 'hidden'
			})
			.scrollLeft((o.playOrder == 'ascending') ? 0 : $panels.last().attr('rel'));	
			
		} else {
			$holder.css({
				width: $panels.eq(0).innerWidth(),
				height: holderStripDim
			});
		
			$slider.css({
				width: $panels.eq(0).innerWidth(),
				height: ($panels.eq(0).innerHeight() * o.panelsNum),
				overflow: (o.sliderOverflow) ? 'visible' : 'hidden'
			})
			.scrollTop((o.playOrder == 'ascending') ? 0 : $panels.last().attr('rel'));	
		}
		
	}
	
	
	function setMarkers()
	{
		
		$panels.removeClass(o.panelMarkerClass);
		
		if(o.playOrder === 'descending')
		{
			var panelsArray = $($.makeArray($panels).reverse().slice(o.panelsNum - 1));	
			panelsArray.last().addClass(o.panelMarkerClass);
		} else {
			var panelsArray = $panels;	
		}
		
		panelsArray
			.each(function($key,$value){
				var $e = $(this);
				if($key % o.panelsNum === 0)$e.addClass(o.panelMarkerClass);
			});
		
		//Set marked panels
		$markedPanels = $panels.filter(function(){return $(this).hasClass(o.panelMarkerClass);});
		
	}
	
	function setCurrent(oMarker)
	{
		//--Reset
			$panels.removeClass(o.selectedClass);
			
		//--Set current marked panel for the first time
			if(typeof oMarker == 'undefined')
			{
				if(o.playOrder == 'ascending')
				{
					$markedPanels.first().addClass(o.selectedClass);
					if(o.hasAnchors)$anchors.removeClass(o.anchorsCurrentClass).first().addClass(o.anchorsCurrentClass);
				} else {
					$markedPanels.last().addClass(o.selectedClass);
					if(o.hasAnchors)$anchors.removeClass(o.anchorsCurrentClass).last().addClass(o.anchorsCurrentClass);
				}	
			} else {
		//--Set current marked panel when the slider has already been initiated
				
				if(o.hasAnchors)
				{
					var index = $markedPanels.index(oMarker);
					$anchors.removeClass(o.anchorsCurrentClass).eq(index).addClass(o.anchorsCurrentClass);
				}
				
				oMarker.addClass(o.selectedClass);
			
			}
	}
	
	function getClosestMarker(pos)
	{
		if(pos >= $panels.length)
		{
			return $markedPanels.last();	
		} else if(pos <= 0){
			return $markedPanels.first();	
		} else {
			var oPanel = $panels.eq(pos);
		//--If current position is a marker
			if(oPanel.hasClass(o.panelMarkerClass))return oPanel;
		//--Get previous marker panel
			var oPrevious = $panels.eq(pos).prevAll('.' + o.panelMarkerClass);	
			if(oPrevious.length > 0)return oPrevious.first();
		//--Return first marker panel if nothing has been found
			return $markedPanels.first();
		}
	}
	
	function getCurrent()
	{
		return $markedPanels.filter(function(){return $(this).hasClass(o.selectedClass);});	
	}
	
	function getNext()
	{
		var oNext = getCurrent().nextAll('.' + o.panelMarkerClass);
		if(oNext.length > 0)return oNext.first();
		return $markedPanels.first();	
	}
	
	function getPrevious()
	{
		var oPrevious = getCurrent().prevAll('.' + o.panelMarkerClass);
		if(oPrevious.length > 0)return oPrevious.first();
		return $markedPanels.last();	
	}
	
	function isLastMarker(oMarker)
	{
		if($markedPanels.index(oMarker) === ($markedPanels.length - 1))return true;//If this is the first marker return true
		//return (oMarker.nextAll('.' + o.panelMarkerClass).length == 0);	
		return false;
	}
	
	function isFirstMarker(oMarker)
	{
		
		if($markedPanels.index(oMarker) === 0)return true;//If this is the first marker return true
		//return (oMarker.prevAll('.' + o.panelMarkerClass).length == 0);	
		return false;
	}
	
	function isDummy(oMarker)
	{
		return (oMarker.hasClass(o.repeatItemClass));	
	}
	/*
	function hasDummy()
	{
		return ($panels.filter(function(){return $(this).hasClass(o.repeatItemClass);}).length === 1);	
	}
	*/
	
	function getUpcomingMarker()
	{
		var curMarker = getCurrent();
		var isLast = isLastMarker(curMarker);
		var isFirst = isFirstMarker(curMarker);
		
		if(isFirst || isLast)
		{
			if(o.playOrder === 'ascending')
			{
				
			} else {
				
			}
		} else {
			return ((o.playOrder == 'ascending') ? getNext() : getPrevious());
		}
	}
	
	function move(oMarker,func)
	{
	//--Run callback before move
		o.beforeMove.call(this);	
	//--Get offset position to move
		var nRel = parseInt(oMarker.attr('rel'));
	//--Set current
		setCurrent(oMarker);
	//--Animate move
		$slider.stop().animate({
			height: (o.orientation == 'horizontal') ? oMarker.innerHeight() : (oMarker.innerHeight() * o.panelsNum),
			width: (o.orientation == 'vertical') ? oMarker.innerWidth() : (oMarker.innerWidth() * o.panelsNum)
		});
	
		$holder.stop().animate({
			/*
			scrollLeft: (o.orientation == 'horizontal') ? nRel : 0,
			scrollTop: (o.orientation == 'vertical') ? nRel : 0,
			*/
			marginLeft: (o.orientation == 'horizontal') ? ('-' + nRel + 'px') : 0,
			marginTop: (o.orientation == 'vertical') ? ('-' + nRel + 'px') : 0
			/*
			height: (o.orientation == 'horizontal') ? oMarker.innerHeight() : (oMarker.innerHeight() * o.panelsNum),
			width: (o.orientation == 'vertical') ? oMarker.innerWidth() : (oMarker.innerWidth() * o.panelsNum)
			*/
		},o.duration,o.effect,function(){
		
			if(!hasDummy && isLastMarker(oMarker) && (o.playOrder === 'ascending'))
			{
				clear();
				o.playOrder = 'descending';	
				setMarkers();
				setCurrent();
				if(o.continuous)play();	
			}
			
			if(!hasDummy && isFirstMarker(oMarker) && (o.playOrder === 'descending'))
			{
				clear();
				o.playOrder = 'ascending';	
				setMarkers();
				setCurrent();
				if(o.continuous)play();	
			}
			
			if(hasDummy)
			{
				if(isLastMarker(oMarker))
				{
					clear();
					oMarker = $markedPanels.first();
					reposition(oMarker);
					if(o.continuous)play();	
				} else if(isFirstMarker(oMarker)) {
					clear();
					oMarker = $markedPanels.last();
					reposition(oMarker);
					if(o.continuous)play();	
				} else {}
				
			}
			
			if(typeof func != 'undefined')func();
		});
	}
	
	function reposition(oMarker)
	{
	//--Get offset position to move
		var nRel = parseInt(oMarker.attr('rel'));
	//--Set current
		setCurrent(oMarker);
	//--Animate move
		$slider.stop().animate({
			height: (o.orientation == 'horizontal') ? oMarker.innerHeight() : (oMarker.innerHeight() * o.panelsNum),
			width: (o.orientation == 'vertical') ? oMarker.innerWidth() : (oMarker.innerWidth() * o.panelsNum)
		});
	
		$holder.stop().animate({
			marginLeft: (o.orientation == 'horizontal') ? ('-' + nRel + 'px') : 0,
			marginTop: (o.orientation == 'vertical') ? ('-' + nRel + 'px') : 0
		},0);
		
		/*
		$slider.stop().animate({
			scrollLeft: (o.orientation == 'horizontal') ? nRel : 0,
			scrollTop: (o.orientation == 'vertical') ? nRel : 0,
			height: (o.orientation == 'horizontal') ? oMarker.innerHeight() : (oMarker.innerHeight() * o.panelsNum),
			width: (o.orientation == 'vertical') ? oMarker.innerWidth() : (oMarker.innerWidth() * o.panelsNum)
		},0);
		*/
	}
	
	
	function getCloseSiblings(sQuery)
	{
		var siblings = $slider.siblings(sQuery);
		if(siblings.length == 0)
		{
			$slider.parents().each(function($key,$value){
				siblings = $(this).find(sQuery);
				if(siblings.length > 0)return false;
			});
		}
		return siblings;
	}
	
	function setPrevNext()
	{
		var prev = getCloseSiblings(o.prevQuery);
		var next = getCloseSiblings(o.nextQuery);
		
		prev.bind('click',{obj:$slider},function($e){
			if(o.preventPrevNextDefault)$e.preventDefault();
			var curMarker = getCurrent();
			if(!hasDummy && isFirstMarker(curMarker))return;
			clear();
			
			if(hasDummy && isFirstMarker(curMarker))
			{
				oMarker = $markedPanels.last();
				reposition(oMarker);
			}
			
			move(getPrevious(),function(){if(o.continuous)play();});
		});
		
		next.bind('click',{obj:$slider},function($e){
			if(o.preventPrevNextDefault)$e.preventDefault();
			var curMarker = getCurrent();
			if(!hasDummy && isLastMarker(curMarker))return;
			clear();
			
			if(hasDummy && isLastMarker(curMarker))
			{
				oMarker = $markedPanels.first();
				reposition(oMarker);
			}
			
			move(getNext(),function(){if(o.continuous)play();});	
		});
		
	}
	
	function setAnchors()
	{
		$anchors = getCloseSiblings(o.anchorsQuery);	
		
		if(hasDummy)
		{
			var panelCount = 	$markedPanels.length - 1;
		} else {
			var panelCount = 	$markedPanels.length;	
		}
		
		if($anchors.length != panelCount)
		{
			$anchors = null;
			o.hasAnchors = false;
			return;
		}
		
		$anchors.bind(o.anchorsEvent,function($e){
			if(o.preventAnchorsDefault)$e.preventDefault();
			var index = $anchors.index(this);
			$anchors.removeClass(o.anchorsCurrentClass);
			$(this).addClass(o.anchorsCurrentClass);
			move($markedPanels.eq(index));	
		});
	}
	
	
	
	
	
	function clear()
	{
		if(interval)
		{
			clearInterval(interval);
			interval = null;
		}	
	}
	
	function play()
	{
		
		clear();
		
		o.continuous = true;
		
		interval = setInterval(function(){
			move((o.playOrder == 'ascending') ? getNext() : getPrevious());
		},o.interval);
		
		
	}
	
	function pause()
	{
		
		clear();
		
		o.continuous = false;
	}
	
	
	

// ---------------------------------------------------------------------------------------	END		-	PRIVATE METHODS

// ---------------------------------------------------------------------------------------	START	-	PUBLIC PROPERTIES
// ---------------------------------------------------------------------------------------	END		-	PUBLIC PROPERTIES

// ---------------------------------------------------------------------------------------	START	-	PUBLIC METHODS	

	this.move = function(settings){
		var s = $.extend({
			pos: 0	
		},settings);
		var oMarker = getClosestMarker(s.pos);
		move(oMarker);		
	};
	
	this.reposition = function(settings){
		var s = $.extend({
			pos: 0	
		},settings);
		var oMarker = getClosestMarker(s.pos);
		reposition(oMarker);
	};
	
	this.play = function(settings){
		var s = $.extend({
			
		},settings);
		play();
	};
	
	this.pause = function(settings){
		var s = $.extend({
			
		},settings);
		pause();
	};
	
	
	


// ---------------------------------------------------------------------------------------	END		-	PUBLIC METHODS

// ---------------------------------------------------------------------------------------	START	-	INIT

	return this.each(function(){
		
		$slider = $(this);
		$holder = $slider.find(o.holderQuery);
		$panels = $holder.find(o.panelsQuery);
		
	//----- Create repeat panel
	
		if(o.repeatable)
		{
			if(o.playOrder == 'ascending')
			{
				$holder.find(o.panelsQuery).eq(0).clone().addClass(o.repeatItemClass).appendTo($holder);
			} else {
				$holder.find(o.panelsQuery).last().clone().addClass(o.repeatItemClass).prependTo($holder);
			}
			hasDummy = true;
		}
		
	//----- Reset $panels to include repeat panel
		$panels = $holder.find(o.panelsQuery);
		
	//----- Setup elements
		setUp();
		
	//----- Set markers on panels
		setMarkers();
		
	
		//--------------------------------------	Set up anchors
		if(o.hasAnchors)setAnchors();
		
		/*
		
		if(o.hasPlayPause)setPlayPause.call($slider);
		
		if(o.hasPrevNext)setPrevNext.call($slider);
		
		o.afterInitialized.call($slider);
		
		
		*/
		
		//----- Set current
		setCurrent();
		
		if(o.hasPrevNext)setPrevNext();
		
		if(o.continuous)play();
		
	});
	//return $slider;
	
// ---------------------------------------------------------------------------------------	END		-	INIT
	
		
};
	
})( jQuery );























