// ---------------------------------------------------------------------------------------	START	-
// ---------------------------------------------------------------------------------------	END		-

(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',
		
		hasAnchors: false,
		anchorsQuery: '.slider-nav a',
		preventAnchorsDefault: true,
		anchorsEvent: 'click',
		
		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;
		o.reversible = false;
		o.resizable = false;
		o.hasAnchors = false;
	}
	
	if(!o.continuous)
	{
		o.playOrder = 'ascending'
	}
	
// ---------------------------------------------------------------------------------------	END		-	SETTINGS			
	
// ---------------------------------------------------------------------------------------	START	-	PRIVATE PROPERTIES


	var slides = new Array();


// ---------------------------------------------------------------------------------------	END		-	PRIVATE PROPERTIES

// ---------------------------------------------------------------------------------------	START	-	PRIVATE METHODS

	function getCloseSiblings(sQuery)
	{
		var siblings = this.siblings(sQuery);
		if(siblings.length == 0)
		{
			this.parents().each(function($key,$value){
				siblings = $(this).find(sQuery);
				if(siblings.length > 0)return false;
			});
		}
		return siblings;
	}
	
	function setPrevNext()
	{
		var prev = getCloseSiblings.call(this,o.prevQuery);
		var next = getCloseSiblings.call(this,o.nextQuery);
		
		prev.bind('click',{obj:this},function($e){
			if(o.preventPrevNextDefault)$e.preventDefault();
			
			if(!o.repeatable && getCurrentPosition.call($e.data.obj) == 0)return;
			if(getCurrentPosition.call($e.data.obj) == 0 && getCurrentPosition.call($e.data.obj) == 0)return;
			
			if($e.data.obj[0].interval)
			{
				clearInterval($e.data.obj[0].interval);
				$e.data.obj[0].interval = null;
			}
			
			if(o.continuous)
			{
				move.call($e.data.obj,getPreviousPosition.call($e.data.obj),play);
			} else {
				move.call($e.data.obj,getPreviousPosition.call($e.data.obj));
			}
		});
		
		next.bind('click',{obj:this},function($e){
			if(o.preventPrevNextDefault)$e.preventDefault();
			
			var $panels = $e.data.obj.find(o.panelsQuery);
			
			if(!o.repeatable && getCurrentPosition.call($e.data.obj) == ($panels.length - 1))return;
			if(o.playOrder == 'descending' && getCurrentPosition.call($e.data.obj) == ($panels.length - 1))return;
			
			if($e.data.obj[0].interval)
			{
				clearInterval($e.data.obj[0].interval);
				$e.data.obj[0].interval = null;
			}
			
			if(o.continuous)
			{
				move.call($e.data.obj,getNextPosition.call($e.data.obj),play);
			} else {
				move.call($e.data.obj,getNextPosition.call($e.data.obj));
			}
		});
		
	}
	
	function isStartOrEndSlide()
	{
		//var $(this).find(o.panelsQuery);	
	}
	
	function setAnchors()
	{
		var obj = this;
		var anchors = getCloseSiblings.call(this,o.anchorsQuery);
		if(anchors.length == 0)return;
		
		anchors.bind(o.anchorsEvent,{obj:this},function($e){
			if(o.preventAnchorsDefault)$e.preventDefault();
			var sText = $(this).text();
			var anchors = getCloseSiblings.call($e.data.obj,o.anchorsQuery);
			var pos = anchors.index(this);
			/*
			var pos = 0;
			anchors.each(function($key,$value){
				if($(this).text() == sText)
				{
					if(obj.find(o.panelsQuery).hasClass(o.repeatItemClass))
					{
						if(o.playOrder == 'ascending')
						{
							pos = $key - 1;
						} else {
							pos = $key + 1;
						}
					} else {
						pos = $key;
					}
					return false;
				}
			});
			*/
			if($e.data.obj[0].interval)
			{
				clearInterval($e.data.obj[0].interval);
				$e.data.obj[0].interval = null;
			}
			
			if(o.continuous)
			{
				move.call($e.data.obj,pos,play);
			} else {
				move.call($e.data.obj,pos);	
			}
		});
	}
	
	function setPlayPause()
	{
		var obj = this;
		var anchor = getCloseSiblings.call(this,o.playPauseQuery);
		if(anchor.length == 0)return;
		
		anchor.bind(o.playPauseEvent,{obj:this},function($e){
			if(o.preventPlayPauseDefault)$e.preventDefault();
			if(obj[0].interval)
			{
				pause.call($e.data.obj);		
			} else {
				play.call($e.data.obj);
			}
			
		});
	}
	
	function setCurrentAnchor(pos)
	{
		if(!o.hasAnchors)return;
		var anchors = getCloseSiblings.call(this,o.anchorsQuery);
		anchors.removeClass(o.selectedClass).eq(pos).addClass(o.selectedClass);
	}
	
	
	function getCurrentPosition()
	{
		return this.find(o.panelsQuery).index(this.find('.' + o.selectedClass));
	}
	
	function getNextPosition()
	{
		var curPos = getCurrentPosition.call(this);
		for(var i = (curPos + 1); i <  this.find(o.panelsQuery).length; i++)
		{
			if(this.find(o.panelsQuery).eq(i).hasClass(o.panelMarkerClass))return i;
		} 
		return 0;
	}
	
	function getPreviousPosition()
	{
		var curPos = getCurrentPosition.call(this);
		for(var i = (curPos - 1); i >=  0; i--)
		{
			if(this.find(o.panelsQuery).eq(i).hasClass(o.panelMarkerClass))return i;
		} 
		return this.find(o.panelsQuery).index(this.find('.' + o.panelMarkerClass).last());
	}
	
	function setCurrentPanel(pos)
	{
		this.find(o.panelsQuery).removeClass(o.selectedClass).eq(pos).addClass(o.selectedClass);
	}
	
	function reverse()
	{
		if(o.reversible)
		{
			o.playOrder = (o.playOrder == 'descending') ? 'ascending' : 'descending';
			play.call(this);
		}
	}
	
	function play(e)
	{
		var obj = this;
		if(obj[0].interval)
		{
			clearInterval(obj[0].interval);
			obj[0].interval = null;
		}
		
		var getPos = (o.playOrder == 'ascending') ? getNextPosition : getPreviousPosition; 
		
		obj[0].interval = setInterval(function(){
			
			move.call(obj,getPos.call(obj));
			
		},o.interval);
		o.onPlay.call(obj);
	}
	
	function pause()
	{
		var obj = this;
		if(obj[0].interval)
		{
			clearInterval(obj[0].interval);
			obj[0].interval = null;
		}	
		o.onPause.call(obj);
	}
	
	function move(pos,func)
	{
		o.beforeMove.call(this);
		
		var obj = this;
		var panel = this.find(o.panelsQuery).eq(pos);
		
		this.animate({
			scrollLeft: (o.orientation == 'horizontal') ? panel.attr('rel') : 0,
			scrollTop: (o.orientation == 'vertical') ? panel.attr('rel') : 0,
			height: (o.orientation == 'horizontal') ? panel.innerHeight() : panel.innerHeight() * o.panelsNum,
			width: (o.orientation == 'vertical') ? panel.innerWidth() : panel.innerWidth() * o.panelsNum
		},getRelativeEffectDuration.call(obj,pos),o.effect,function(){
			
			if(o.repeatable && obj.find(o.panelsQuery).eq(pos).hasClass(o.repeatItemClass))
			{
				if(o.playOrder == 'descending')
				{
					pos = obj.find(o.panelsQuery).length - 1;
					if(o.orientation == 'horizontal')
					{
						obj.scrollLeft(obj.find(o.panelsQuery).eq(pos).attr('rel'));
					} else {
						obj.scrollTop(obj.find(o.panelsQuery).eq(pos).attr('rel'));
					}
				} else {
					pos = 0;
					obj.scrollLeft(0).scrollTop(0);
				}
			}
			
			setCurrentPanel.call(obj,pos);
			setCurrentAnchor.call(obj,(o.playOrder == 'descending' && o.repeatable) ? pos - 1 : pos);
			
			if(!o.repeatable  && o.playOrder == 'ascending' && getNextPosition.call(obj) < pos && o.reversible)reverse.call(obj);
			if(!o.repeatable  && o.playOrder == 'descending' && getPreviousPosition.call(obj) > pos && o.reversible)reverse.call(obj);
			
			if(typeof func != 'undefined')func.call(obj);
			
			o.afterMove.call(obj);
			
		});
	}
	
	function getRelativeEffectDuration(newPos)
	{
		var pos = getCurrentPosition.call(this);
		var diff = (pos > newPos) ? (pos - newPos) : (newPos - pos);
		if(diff == 1)return o.duration;
		return Math.round(o.duration + (diff * (o.duration / o.durationFraction)));
	}
	

// ---------------------------------------------------------------------------------------	END		-	PRIVATE METHODS

// ---------------------------------------------------------------------------------------	START	-	PUBLIC PROPERTIES
// ---------------------------------------------------------------------------------------	END		-	PUBLIC PROPERTIES

// ---------------------------------------------------------------------------------------	START	-	PUBLIC METHODS	

	this.play = function(settings){
		var s = $.extend({
			pos: 0
		},settings);
		play.call($(this).eq(s.pos));
		return this;
	};
	
	this.pause = function(settings){
		var s = $.extend({
			pos: 0
		},settings);
		pause.call($(this).eq(s.pos));
		return this;	
	};


// ---------------------------------------------------------------------------------------	END		-	PUBLIC METHODS

// ---------------------------------------------------------------------------------------	START	-	INIT

	return this.each(function(){
		
		var $rotator = $(this);
		var $holder = $rotator.find(o.holderQuery);
		var $panels = $holder.find(o.panelsQuery);
		
		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);
			}
		}
		var $panels = $holder.find(o.panelsQuery);
		
		
		var holderStripDim = 0;
			
		$panels.each(function($key,$value){
			var $e = $(this);
		
			$e.css({
				width: (!o.panelWidthCalculation) ? $e.innerWidth() : o.panelWidthCalculation.call($e),
				height: $e.innerHeight(),
				float: 'left'
			}).attr('rel',holderStripDim);
		
			if($key == 0)
			{
				$e.addClass(o.panelMarkerClass);
			} else {
				if($key % o.panelsNum == 0)
				{
					if($key < ($panels.length - o.panelsNum))
					{
						$e.addClass(o.panelMarkerClass);
					} else {
						$panels.eq($panels.length - o.panelsNum).addClass(o.panelMarkerClass);
					}
				}
			}
		
			holderStripDim += (o.orientation == 'horizontal') ? $e.innerWidth() : $e.innerHeight();
		});
	
		$holder.css({
			width: (o.orientation == 'horizontal') ? holderStripDim : $panels.eq(0).innerWidth(),
			height: (o.orientation == 'horizontal') ? $panels.eq(0).innerHeight() : holderStripDim
		});
	
		$rotator.css({
			width: (o.orientation == 'horizontal') ? ($panels.eq(0).innerWidth() * o.panelsNum) : $panels.eq(0).innerWidth(),
			height: (o.orientation == 'horizontal') ? $panels.eq(0).innerHeight() : ($panels.eq(0).innerHeight() * o.panelsNum),
			overflow: 'hidden'
		});
	
		if(o.orientation ==  'horizontal')
		{
			$rotator.scrollLeft((o.playOrder == 'ascending') ? 0 : $panels.last().attr('rel'));
		} else {
			$rotator.scrollTop((o.playOrder == 'ascending') ? 0 : $panels.last().attr('rel'));
		}
		
		
		if(o.playOrder == 'ascending')
		{
			$holder.find('.' + o.panelMarkerClass).first().addClass(o.selectedClass);
			setCurrentAnchor.call($rotator,0);
		} else {
			$holder.find('.' + o.panelMarkerClass).last().addClass(o.selectedClass);
			setCurrentAnchor.call($rotator,$holder.find('.' + o.panelMarkerClass).not('.' + o.repeatItemClass).length - 1);
		}
		
		//--------------------------------------	Set up anchors
		if(o.hasAnchors)setAnchors.call($rotator);
		
		if(o.hasPlayPause)setPlayPause.call($rotator);
		
		if(o.hasPrevNext)setPrevNext.call($rotator);
		
		o.afterInitialized.call($rotator);
		
		if(o.continuous)play.call($rotator);
		
	});
	
// ---------------------------------------------------------------------------------------	END		-	INIT
	
		
};
	
})( jQuery );























