(function($){

	/*
		Created:
		10.01.2011 | Michal Matuška
		
		Updates:
		13.07.2011 | Upraveno pro podporu jQuery 1.6
		
		Fixed bugs:
		13.07.2011 | oprava stránkování při nekonečném carouselu
	*/

   	var aztower = window.aztower = window.aztower || {};

	aztower.Carousel = function (element, options){
		
		this.$element = $(element);
		this.options = $.extend({
			item: 'li', // elementy ktere se budou scrollovat
			visible: 2, // počet viditelných elementů
			animation: 500, // čas za který se provede animace kroku
			easing: 'swing',
			boxClass: 'carousel-box', 
			spcClass: 'carousel-spc',
			clipClass: 'carousel-clip',	
			axis: 'x', // x, y
			htmlPager: '.pager',
			pause: false,
			repeat: false, // opakovat
			pauseOnHover: '',
			pagerPages: true,
			pagerMask: '', // {$active} = aktivní položka, {$all} = celkový počet
			timeout: 5000,
			auto: true,
			onScroll: false
		}, options)
		
		this.paused = false;
		this.$items = this.$element.find(this.options .item);
		this.length = this.$items.length;
		this.visible = this.options.visible;
		this.end = this.length - this.visible;
		this.animate = false;
		this.current = 0;
		this.axProps = this.options.axis == 'x' ? 
			{
				left: 'left',
				width: 'width',
				outerWidth: 'outerWidth',
				scrollWidth: 'scrollWidth',
				scrollLeft: 'scrollLeft',
				offset: 'offsetLeft'
			} :
			{
				left: 'top',
				width: 'height',
				outerWidth: 'outerHeight',
				scrollWidth: 'scrollHeight',
				scrollLeft: 'scrollTop',
				offset: 'offsetTop'
			};
		
		return this;
	};
	
	aztower.Carousel.prototype = {
		
		constructor: aztower.Carousel,
		
		// reference na jquery proxy
		proxy : $.proxy,
		
		// reference na globální objekt Math
		abs: Math.abs,
			
		init: function() {
			if(this.$element.data('carouselInit') || !this.$element.length || !this.end)
			{
				return this;
			}
			
			var o = this.options,
				e = this.$element;
				
			// repeat init
			if(o.repeat){
				this.$items
					.slice(0, this.visible)
					.clone()
					.addClass('clone')
					.appendTo(this.$element);
				
				this.$items
					.slice(this.length-this.visible, this.length)
					.clone()
					.addClass('clone')
					.prependTo(this.$element);
					
				this.$items = this.$element.find(this.options .item);
				this.current = this.current+this.visible;
			}
			
			// vypočítání pozic elementů - nemusí se pořád dokola zjišťovat
			this.offsets = [];
			for (var i=0, l=this.$items.length; i < l; i++) {
				this.offsets[i] = this.$items.get(i)[this.axProps.offset];
			};
			
			this.$items[this.axProps.width](function(i, old){ return old });
		
			e
				.wrap('<div class="'+ o.boxClass +'"><div class="'+ o.spcClass +'"><div class="'+ o.clipClass +'"></div></div></div>')
				[this.axProps.width](e.prop('scrollWidth'))
				[this.axProps.scrollLeft](0)
				.css({'overflow':'visible', 'position':'relative'})
				.css(this.axProps.left, -this.offsets[this.current]+'px')
				.data('carouselInit', true);
				
			this.$box = e.closest('.' + o.boxClass);
			this.$spc = e.closest('.' + o.spcClass);
			this.$clip = e.closest('.' + o.clipClass);
			this.$pager = $(o.htmlPager);
			
			
			if(this.$pager.length){
				var pager = [];
				// prev
				pager.push('<a href="#" class="prev"><span class="out">předchozí</span></a>');
				// page
				if(o.pagerPages && !o.pagerMaks){
					pager.push('<span class="pages">')
					for (var i=0, l=Math.ceil(this.length/this.visible); i < l; i++) {
						pager.push('<a href="#" class="page">'+ (i+1) +'</a>');
					};
					pager.push('</span>')
				}
				else if(o.pagerMask){
					pager.push('<span class="pages"></span>')	
				}
				// next
				pager.push('<a href="#" class="next"><span class="out">další</span></a>');
				
				// pause
				o.pause && pager.push('<a href="#" class="control"></a>');
				
				// create pager
				this.$pager
					.append(pager.join(' '))
					.delegate('.control', 'click', this.proxy(this.control, this))
					.delegate('.page', 'click', this.proxy(this.page, this))
					.delegate('.prev', 'click', this.proxy(this.prev, this))
					.delegate('.next', 'click', this.proxy(this.next, this));
				
	            // počáteční nastavení	
				(o.pagerPages && !o.pagerMaks) && this.getPage();
				(o.pagerMask) && this.getPages();
				
				(!o.repeat) && this.controlPrev();
				(!o.repeat) &&this.controlNext();
				
				this.getControl();
			}
			
			if(o.pauseOnHover){
	            $(document)
	                .delegate(o.pauseOnHover, 'mouseenter', this.proxy(function(){
	                       this.clearInterval();
	                       this.paused = true;
	                       this.getControl();
	                }, this))
	                .delegate(o.pauseOnHover, 'mouseleave', this.proxy(function(){
	                       this.resetInterval();
	                       this.paused = false;
	                       this.getControl();
	                }, this))
	        }
			
			this.resetInterval();
			return this;
		},
		// metoda pro zjištění zda je daný element plně vidět ve výřezu
		isVisible: function(i){
			var cW = this.$clip[this.axProps.width](),
				cOff = this.offsets[this.current],
				iW = this.$items.eq(i)[this.axProps.outerWidth](),
				iOff = this.offsets[i];	
			
			return (cOff <= iOff && (cW+cOff) >= (iW + iOff));
		},
		getVisible: function(){
			var count = 0;
			
			for(var i = 0, l = this.$items.length; i < l; i++){
				this.isVisible(i) && count++;	
			}
			
			return count;
		},
		interval: function()
		{
			this.next();
		},
		clearInterval: function()
		{
			this.mainTimer = clearTimeout(this.mainTimer);
		},
		resetInterval: function()
		{
			if(this.options.auto){
				this.mainTimer = clearTimeout(this.mainTimer);
				this.mainTimer = setTimeout(this.proxy(function(){this.interval()}, this), this.options.timeout);
			}
		},
		control: function() {
			this.paused = !this.paused;
			this.getControl();
			this.paused ? this.clearInterval() : this.resetInterval();
		},
		next: function() {
			var i = this.current + this.visible;	
			this.scrollTo(i);
			return false;
		},
		prev: function() {
			var i = this.current - this.visible;
			this.scrollTo(i);
			return false;	
		},
		page: function(e) {
			// pokud je opakovani musi byt hodnota navysena o pocet scrollovanych
			var i = $(e.target).index() * this.visible + (this.options.repeat ? this.visible : 0);
			this.scrollTo(i);
			return false;	
		},
		scrollTo: function(i, type) {
			var o = this.options;
			
			if(!o.repeat)
			{
				var i = i < 0 ? 0 : i;
				i = i > this.end ? this.end : i;	
			}
			
			if(i != this.current /*&& !this.animate*/ )
			{
				this.animate = true;
				var props = {};
					props[this.axProps.left] = -this.offsets[i];
				// animace
				this.$element
					.stop()
					.animate(
						props, 
						o.animation, 
						o.easing,
						this.proxy(function(){
							this.animate = false;
							!this.paused && this.resetInterval();
							if (o.repeat){
								if(i < this.visible)
								{
									this.$element.css(this.axProps.left, -this.offsets[this.length]);
									return;	
								}
								if(i > this.length)
								{
									this.$element.css(this.axProps.left, -this.offsets[this.visible]);
									return;
								}	
							}
							
						}, this)
					);
					
				if(o.repeat)
				{
					this.current = (i < this.visible) ? this.length : (i > this.length) ? this.visible : i;
				}
				else
				{
					this.current = i	
				}
				
				typeof o.onScroll == 'function' && o.onScroll.call(this, i);
				
				(o.pagerPages && !o.pagerMaks) && this.getPage();
				(o.pagerMask) && this.getPages();
				
				(!o.repeat) && this.controlPrev();
				(!o.repeat) &&this.controlNext();
			}
	
		},
		// nastaví přehrávacího tlačítka
		getControl: function(){
			this.$pager
				.find('.control')
				.removeClass(this.paused ? 'pause' : 'play')
				.addClass(this.paused ? 'play' : 'pause')
				.text(this.paused ? 'play' : 'pause');
		},
		// nastaví správné stránkování
		getPage: function(){
			this.$pager
				.find('.page')
				.removeClass('active')
				.eq((this.current - this.visible) / this.visible)
				.addClass('active');	
		},
		// nastaví správné stránkování (stránkován s maskou)
		getPages: function(){
			this.$pager
				.find('.pages')
				.text(this.options.pagerMask.replace('{$active}', this.current).replace('{$all}', this.length))	
		},
			
		controlPrev: function() {
			this.$pager
				.find('.prev')[(this.current == 0) ? 'addClass' : 'removeClass']('prev-disable');
		},
		controlNext: function() {
			this.$pager
				.find('.next')[(this.current == this.end) ? 'addClass' : 'removeClass']('next-disable');
		}
	
		
	};

})(jQuery);
