(function($) {
$.fn.carousel = function(settings) {
	var config = {
		sizeBigWidth: 190,
		sizeBigHeight: 210,
		sizeSmallWidth: 110,
		sizeSmallHeight: 122,
		pause: 5000,
		speed: 500,
		nextEl: null,
		prevEl: null,
		fadeTo: 0.5,
		autostart: false
	};

	if (settings) $.extend(config, settings);

	this.each(function() {

		var me = this;
		var $me = $(me);
		var items = $me.find('img');
		var itemsCount = items.length;
		var currentIndex = 1;
		
		var wrapSize = {
			width: $me.width(),
			height: $me.height()
		};

		var cellSize = {
			width: Math.floor(wrapSize.width / 3),
			height: wrapSize.height
		};

		var bigItem = {
			offset: {
				x: Math.floor((cellSize.width - config.sizeBigWidth) / 2),
				y: 0
			}
		};

		var smallItem = {
			offset: {
				x: Math.floor((cellSize.width - config.sizeSmallWidth) / 2),
				y: 0
			}
		};

		var positions = {
			left: {
				top: 0,
				left: 0
			},
			current: {
				top: 0,
				left: 0
			},
			right: {
				top: 0,
				left: 0
			}
		};

		var lock = false;

		this.init = function() {

			$me.css('position', 'relative');

			for (i = 0; i <= itemsCount; i++) {
				
				var current = items[i];
				var $current = $(current);
				var indexes = this.getIndexes();

				$current.css({
					position: 'absolute',
					opacity: 0.5
				});


				if ( i == indexes.left || i == indexes.right ) {
					
					this.resize($current, true);

					if ( i == indexes.left ) {
						positions.left.left = (cellSize.width * i) + smallItem.offset.x;
						$current.css(positions.left);
					} else {
						positions.right.left = (cellSize.width * i) + smallItem.offset.x;
						$current.css(positions.right);
					}
					
				} else if ( i == indexes.current ) {

					positions.current.top = bigItem.offset.y;
					positions.current.left = (cellSize.width * i) + bigItem.offset.x;
					$current.css({
						top: positions.current.top,
						left: positions.current.left,
						opacity: 1
					});
					this.resize($current, false);
					
				} else {
					$current.hide();
				}
			}

			//event binding
			if (config.nextEl != null)
				$(config.nextEl).click(this.slideToLeft);
		};
		
		this.resize = function($item, small) {
			if (small == undefined) small = false;
			var sizeW = (small) ? config.sizeSmallWidth : config.sizeBigWidth;
			var sizeH = (small) ? config.sizeSmallHeight : config.sizeBigHeight;

			$item.css({
				position: 'absolute',
				width: sizeW,
				height: sizeH
			}).attr({
				width: sizeW,
				height: sizeH
			});
		};

		this.getIndexes = function() {
			indexes = {};
			indexes.current = currentIndex;
			indexes.left	= (indexes.current == 0) ? itemsCount - 1 : indexes.current-1;
			indexes.right	= (indexes.current == (itemsCount-1)) ? 0 : indexes.current+1;
			indexes.next	= (indexes.right == (itemsCount - 1)) ? 0 : indexes.right+1;

			return indexes;
		};

		this.slideToLeft = function() {

			if (lock) return;
			lock = true;

			indexes = me.getIndexes();
			$current = $(items[indexes.current]);
			$left = $(items[indexes.left]);
			$right = $(items[indexes.right]);
			$next = $(items[indexes.next]);
			
			$current.removeClass('current');
			$right.addClass('current');

			$left.fadeOut(config.speed);
			
			$current.animate({
				top: positions.left.top,
				left: positions.left.left,
				width: config.sizeSmallWidth,
				height: config.sizeSmallHeight,
				opacity: config.fadeTo
			}, config.speed);

			$right.animate({
				top: positions.current.top,
				left: positions.current.left,
				width: config.sizeBigWidth,
				height: config.sizeBigHeight,
				opacity: 1
			}, config.speed);

			me.resize($next, true);
			$next.css(positions.right);
			$next.fadeIn(config.speed, me.unlock);

			++currentIndex;
			if (currentIndex >= itemsCount)
				currentIndex = 0;
		};

		this.cycle = function() {
			setTimeout(me.cycle, config.pause);
			me.slideToLeft();
		};

		this.unlock = function() {
			lock = false;
		}


		this.init();

		if (config.autostart)
			setTimeout(this.cycle, config.pause);
	});

	return this;
};
})(jQuery);
