jQuery.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
		boxClass: 'carousel-box', 
		spcClass: 'carousel-spc',
		clipClass: 'carousel-clip',	
		axis: 'x', // x, y
		htmlPager: '.pager',
		pagerPages: true,
		pagerMask: '', // {$active} = aktivní položka, {$all} = celkový počet
		timeout: 5000,
		auto: true
	}, options)
	
	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'
		};

};

jQuery.Carousel.prototype = {
	
	constructor: jQuery.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)
		{
			return this;
		}
		
		var o = this.options,
			e = this.$element;
			
		// repeat init
		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];
		};
	
		e
			.css({'overflow':'visible', 'position':'relative'})
			.css(this.axProps.left, -this.offsets[this.current]+'px')
			.wrap('<div class="'+ o.boxClass +'"><div class="'+ o.spcClass +'"><div class="'+ o.clipClass +'"></div></div></div>')
			[this.axProps.width](e.attr(this.axProps.scrollWidth))
			[this.axProps.scrollLeft](0)
			.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.end && this.$pager.length){
			var pager = [];
			// prev
			pager.push('<a href="#" class="prev"></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 ? ' active':'') +'">'+ (i+1) +'</a>');
				};
				pager.push('</span>')
			}
			else if(o.pagerMask){
				pager.push('<span class="pages">' + o.pagerMask.replace('{$active}', this.current).replace('{$all}', this.length) +'</span>')	
			}
			// next
			pager.push('<a href="#" class="next"></a>');
			
			// create pager
			this.$pager
				.append(pager.join(' '))
				.delegate('.page', 'click', this.proxy(this.page, this))
				.delegate('.prev', 'click', this.proxy(this.prev, this))
				.delegate('.next', 'click', this.proxy(this.next, 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);
		}
	},
	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) {
		var i = (parseInt($(e.target).text())) * this.visible;
		this.scrollTo(i);
		return false;	
	},
	scrollTo: function(i, type) {
		var o = this.options;
			
		if(i != this.current && !this.animate )
		{
			this.animate = true;
			var props = {};
				props[this.axProps.left] = -this.offsets[i];
			// animace
			this.$element
				.animate(
					props, 
					o.animation, 
					'swing',
					this.proxy(function(){
						this.animate = false;
						this.resetInterval();
						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)
				);
				
		
			this.current = (i < this.visible) ? this.length : (i > this.length) ? this.visible : i;
			(o.pagerPages && !o.pagerMaks) && this.controlPage();
			(o.pagerMask) && this.controlPages();
		}

	},
	controlPage: function(){
		this.$pager
			.find('.page')
			.removeClass('active')
			.eq((this.current - this.visible) / this.visible)
			.addClass('active');	
	},
	controlPages: function(){
		this.$pager
			.find('.pages')
			.text(this.options.pagerMask.replace('{$active}', this.current).replace('{$all}', this.length))	
	}


	
};


