// --------------------------------------------------
//
// Carousel
//
// USAGE: Carousel = new PP2.carousel(target, options);
//
// AUTHOR: MC
//
// DEPENDENCIES:
// jQuery 1.6 or later
//
// --------------------------------------------------

PP2.Carousel = function(target, options){
	var base = this;

	base.options = $.extend({
		elWrapper: null,				// wrapper element
		slider: false,					// vertically slide content
		panelTitleSelector: null,		// button/tab text
		contentSelector: null,			// content element for fancy load in
		btnElement: null,				// override default button element
		currentIndex: 0,				// index for first content loaded
		maxItems: 10,					// max items in switcher
		cycleSpeed: 6000,				// speed through auto cycle
		panelSwitchDuration: 1000,		// duration for switching panels
		autoCycle: false,				// boolean for auto cycling
		pagination: false,				// boolean for pagination buttons
		arrows: false,					// boolean for arrow buttons
		showNext: false,				// boolean for displaying next panel title
		showNextText: 'Next: ',			// next text indicator
		itemCount: false,				// boolean for item count display
		itemCountSeparator: ' of ',		// set separator for item count
		onPanelLoad: function(){},		// happens when a new panel is loaded
		onPaginationClick: function(){},		// happens when a new panel is loaded
		callback: function(){}			// happens on instantiation
	}, options || {});

	base.elPanel = target;
	base.animating = false;
	base.elWrapper = !!base.options.elWrapper ? base.options.elWrapper : base.elPanel.parent();

	base.init();
	base.options.callback();
};

PP2.Carousel.prototype = {
	init: function () {
		var base = this, i, ii, contentNodeLeftPosition,
			elContentNodes = $(base.elWrapper).find(base.options.contentSelector),
			elFrame = $('<div class="frame" />');

		if (base.options.slider) {
			base.elPanel.parent().width(base.elPanel.first().width() * (base.elPanel.length));

			base.elWrapper = base.elWrapper.is('ul') ? base.elWrapper.parent() : base.elWrapper;

			elFrame.append(base.elPanel.parent());
			base.elWrapper.prepend(elFrame);
		} else {
			// hide all panels except the default panel
			base.elPanel.hide();
		}

		// cache current panel
		base.elCurrentPanel = $(base.elPanel[base.options.currentIndex]);

		elContentNodes.hide();

		base.elCurrentPanel.show().addClass('on');
		base.elCurrentPanel.find(base.options.contentSelector).show();

		// fire panel load callback
		base.options.onPanelLoad(base.elCurrentPanel);

		// build out navigation
		base.buildNav();

		// cycle through panels
		if (base.options.autoCycle) {
			base.cycle = setTimeout(function () {
				base.autoCycle();
			}, base.options.cycleSpeed);
		}
	},
	buildNav: function () {
		var base = this, i, ii,
			elNavLink, itemCount,
			elBtnBack, elBtnNext,
			btnText, btnElement,
			elNextPanel, nextPanelText;

		itemCount = base.elPanel.length > base.options.maxItems ? base.options.maxItems : base.elPanel.length;
		btnElement = base.options.btnElement ? base.options.btnElement : 'button';

		if (itemCount > 1) {
			base.elControlsWrapper = $('<div class="panel-controls"></div>');

			// build out pagination/tabs
			if (base.options.pagination) {
				base.elNavPagiWrapper = $('<ul class="nav-panels-pagi" />');

				for (i = 0, ii = itemCount; i < ii; i++) {
					btnText = base.options.panelTitleSelector ? $(base.elPanel[i]).find(base.options.panelTitleSelector).text() : 'Panel ' + (i + 1);
					elNavLink = $('<li><' + btnElement + '>' + btnText + '</' + btnElement + '></li>');

					if (i === base.options.currentIndex) {
						elNavLink.addClass('on');
					}

					base.elNavPagiWrapper.append(elNavLink);
				}

				base.elControlsWrapper.append(base.elNavPagiWrapper);
			}

			// build arrow buttons
			if (base.options.arrows) {
				base.elNavArrowsWrapper = $('<ul class="nav-panels-arrows" />');

				elBtnBack = $('<li class="btn-back"><' + btnElement + '>Back</' + btnElement + '></li>');
				elBtnNext = $('<li class="btn-next"><' + btnElement + '>Next</' + btnElement + '></li>');

				base.elNavArrowsWrapper.append(elBtnBack, elBtnNext);
				base.elControlsWrapper.append(base.elNavArrowsWrapper);

				if (base.options.currentIndex === 0) {
					base.elNavArrowsWrapper.children('li.btn-back').addClass('disabled');
				} else if (base.options.currentIndex === base.elPanel.length - 1) {
					base.elNavArrowsWrapper.children('li.btn-next').addClass('disabled');
				}
			}

			// display item count
			if (base.options.itemCount) {
				base.elCountWrapper = $('<p class="panel-count"></p>');

				base.elCountWrapper.text((base.elCurrentPanel.index() + 1) + base.options.itemCountSeparator + (base.elPanel.length));
				base.elControlsWrapper.append(base.elCountWrapper);
			}

			// display next panal title
			if (base.options.showNext) {
				base.elShowNextWrapper = $('<p class="panel-next"></p>');

				elNextPanel = base.elCurrentPanel[0] !== base.elPanel.last()[0] ? base.elPanel[base.elCurrentPanel.index() + 1] : base.elPanel[0];
				nextPanelText = base.options.showNextText + $(elNextPanel).find(base.options.panelTitleSelector).text();

				base.elShowNextWrapper.text(nextPanelText);
				base.elControlsWrapper.append(base.elShowNextWrapper);
			}

			base.elWrapper.prepend(base.elControlsWrapper);

			var navWidth = (base.elWrapper.width() - base.elControlsWrapper.width()) / 2;
			base.elControlsWrapper.find('ul');
		}

		base.bindEvents();
	},
	bindEvents: function () {
		var base = this,
			index,
			direction;

		// bind click to all pagination/tab buttons
		if (base.elNavPagiWrapper) {
			base.elNavPagiWrapper.children('li').click(function (e) {
				if (!base.animating) {
					base.options.onPaginationClick(base.elPanel[$(this).index()]);
					base.switchPanel($(this).index());

					clearTimeout(base.cycle);
					clearTimeout(base.progressInterval);
				}
			});
		}

		// bind click to arrow buttons
		if (base.elNavArrowsWrapper) {
			base.elNavArrowsWrapper.children('li').click(function (e) {
				if (!base.animating) {
					index = base.elCurrentPanel.prevAll('li').length;
					direction = $(this).hasClass('btn-back') ? 'back' : 'next';

					if (direction === 'back' && index > 0) {
						index = index - 1;
					} else if (direction === 'next' && index < base.elPanel.length - 1) {
						index = index + 1;
					}

					base.options.onPaginationClick(base.elPanel[index]);
					base.switchPanel(index);

					clearTimeout(base.cycle);
					clearTimeout(base.progressInterval);
				}
			});
		}
	},
	switchPanel: function (index) {
		var base = this,
			elTargetPanel,
			elContentNode,
			elContentNodes = $(base.elWrapper).find(base.options.contentSelector),
			elScrollWindow = base.elPanel.parent();

		if (index !== undefined) {
			elTargetPanel = base.elPanel[index];
		} else {
			if (base.elCurrentPanel.next('li').length && base.elCurrentPanel.next('li').index() + 1 <= base.options.maxItems) {
				elTargetPanel = base.elCurrentPanel.next('li');
			} else {
				elTargetPanel = $(base.elPanel[0]);
			}
		}

		elContentNode = $(elTargetPanel).find(base.options.contentSelector);

		if (base.elCurrentPanel[0] !== elTargetPanel && !base.animating) {
			base.animating = true;

			if (base.options.slider) {
				elContentNodes.hide();

				elScrollWindow.stop().animate({
					left: '-' + elTargetPanel.offsetLeft + 'px'
				}, base.options.panelSwitchDuration, function () {
					elContentNode.fadeIn();
				});

				base.elCurrentPanel.removeClass('on');

				$(elTargetPanel).addClass('on');

				base.animating = false;
			} else {
				base.elCurrentPanel.removeClass('on').fadeOut(base.options.panelSwitchDuration / 2);
	
				$(elTargetPanel).addClass('on').fadeIn(base.options.panelSwitchDuration, function () {
					elContentNodes.hide();
					elContentNode.fadeIn();
					base.animating = false;
				});
			}

			base.elPreviousPanel = base.elCurrentPanel;
			base.elCurrentPanel = $(elTargetPanel);

			base.updateUI();

			// fire panel load callback
			base.options.onPanelLoad(base.elCurrentPanel);
		}
	},
	updateUI: function () {
		var base = this,
			elNextPanel,
			nextPanelText;

		// update current panel indicator
		if (base.options.pagination) {
			base.elNavPagiWrapper.children('li').removeClass('on');

			$($('ul.nav-panels-pagi li')[base.elCurrentPanel.prevAll().not('.panel-controls').length]).addClass('on');
		}

		// enable/disable arrows
		if (base.options.arrows) {
			base.elNavArrowsWrapper.children('li').removeClass('disabled');

			if (base.elCurrentPanel.index() === 0) {
				base.elNavArrowsWrapper.children('li.btn-back').addClass('disabled');
			} else if (base.elCurrentPanel.index() === base.elPanel.length - 1) {
				base.elNavArrowsWrapper.children('li.btn-next').addClass('disabled');
			}
		}

		// keep track of current panel
		if (base.options.itemCount) {
			base.elCountWrapper.text((base.elCurrentPanel.index() + 1) + base.options.itemCountSeparator + (base.elPanel.length));
		}

		// show upcoming panel
		if (base.options.showNext) {
			elNextPanel = base.elCurrentPanel[0] !== base.elPanel.last()[0] ? base.elPanel[base.elCurrentPanel.index() + 1] : base.elPanel[0];
			nextPanelText = base.options.showNextText + $(elNextPanel).find(base.options.panelTitleSelector).text();

			base.elShowNextWrapper.text(nextPanelText);
		}
	},
	autoCycle: function () {
		var base = this,
			i = base.elCurrentPanel.index() + 1;

		(function cycleNode() {
			base.switchPanel();
			base.progressInterval = setTimeout(cycleNode, base.options.cycleSpeed);
		})();
	}
};
