$j.fn.tokenCarousel = function () {
	var $ = $j;
	return this.each(function () {

		var constantLimit = limit = 5;

		// Remove surplus arrows
		$('.token-arrow').remove();

		var wrapper = $('> div', this).css('overflow', 'hidden');
		var currentId = wrapper.attr('panagora:id');
		var noToken = wrapper.is('.notoken');
		var slider = wrapper.find('ul');
		var items = slider.find('li');
		var itemIdx = getCurrentIndex(items, currentId);

		addHash();

		var singleHeight = slider.find('li:first').outerHeight();

		// Set new class on current
		if (!noToken)
			items.eq(itemIdx).addClass('selected-token');

		// Scroll to middleish element.
		if (items.eq(itemIdx))
			wrapper.scrollTop(items.eq(itemIdx).get(0).offsetTop - singleHeight);

		function gotoPage(item) {
			var dir = item < itemIdx ? -1 : 1;
			var top = singleHeight * dir;
			var offset = 0;
			var loading = false;

			if (dir > 0) {
				itemIdx++;
			} else {
				itemIdx--;
			}

			if (itemIdx < 0) {
				itemIdx = 0;
			}
			if (itemIdx > items.length) {
				itemIdx = items.length - 1;
			}

			wrapper.filter(':not(:animated)').animate({
				scrollTop : '+=' + top
			}, 500, function () {
				if ((itemIdx - 1 <= 0 && dir < 0) || (itemIdx + 1 >= items.length - 1 && dir > 0) && !loading) {
					loading = true;

					if (dir > 0) {
						offset = parseInt(slider.find('li:last').attr('panagora:offset'), 10) + 1;
						limit = constantLimit;
					} else {
						offset = parseInt(slider.find('li:first').attr('panagora:offset'), 10) - limit;
						if (offset < 0)
							limit = limit + offset
					}

					Panagora.ajax({
						url: wrapper.attr('panagora:src'),
						data: {
							'token': location.hash.substring(1),
							'offset': offset,
							'limit': limit
						},
						dataType: 'text',
						success: function (content) {
							if (dir > 0) {
								slider.find('li:last').after(content);
							} else {
								slider.find('li:first').before(content);
								wrapper.scrollTop(items.eq(itemIdx).get(0).offsetTop - singleHeight);
							}

							// Reset currentId
							currentId = items.eq(itemIdx).attr('panagora:displayproductid');
				
							// Reset slider
							slider = wrapper.find('ul');
							items = slider.find('li');

							// Reset index
							itemIdx = getCurrentIndex(items, currentId);

							addHash();
							loading = false;
						}
					});
				}
			});
			return false;
		}
		
		function getCurrentIndex(elem, id) {
			var currentIndex = 0;
			elem.filter( function (index) {
				if (this.getAttribute('panagora:displayproductid') == id)
					currentIndex = index;
			});
			return currentIndex;
		}
		
		function addHash() {
			var re = new RegExp(location.hash);
			$('.plink', slider).each(function() {
				if (re.test(this.href))
					this.href = this.href.replace(re, '');
			});
			$('.plink', slider).each(function() {
				this.href += location.hash;
			});
		}
		
		// Add arrows
		wrapper.before('<div class="token-arrow back"></div>');
		wrapper.after('<div class="token-arrow forward"></div>');

		// Methods for enabling and disabling arrows
		function disableArrows () { $('.arrow', this).each(function () { this.disabled = false; }); }
		function enableArrows () { $('.arrow', this).each(function () { this.disabled = true; }); }

		// Add events for arrows
		$('div.back', this).click(function () { return gotoPage(itemIdx - 1); });
		$('div.forward', this).click(function () { return gotoPage(itemIdx + 1); });
	});
}

