NetR = typeof NetR === 'undefined' ? {} : NetR;

NetR.Carousel = function (el, options) {
	var t = this;

	this.mode = NetR.Carousel.modes.LOADING;

	this.options = $.extend({}, NetR.Carousel.defaultOptions, options || {});
	this.activePage = 1;
	this.elements = {};

	this.elements.wrapper = $('<div class="js-carousel"></div>');

	if (NetR.String.isOneOf(el.attr('tagName').toLowerCase(), 'ul', 'ol')) {
		this.elements.list = el;
		this.elements.container = el.parent();
	} else {
		this.elements.container = el;
		this.elements.list = el.find('ul,ol');
	}

	this.elements.container.after(this.elements.wrapper);
	this.elements.wrapper.append(this.elements.container);

	this.updateItems();

	this.pageCount = Math.ceil(this.itemCount / this.options.itemsPerPage);

	// Insert cliping div
	this.elements.clip = $('<div class="cf"></div>');
	this.elements.clip.css({
		'overflow': 'hidden',
		'width'   : this.elements.container.width()
	});
	this.elements.container.append(this.elements.clip);
	this.elements.clip.append(this.elements.list);

	// Add empty padding elements if needed to fill up last page
	if (this.itemCount % this.options.itemsPerPage) {
		for (var i = 0, j = (this.options.itemsPerPage - (this.itemCount % this.options.itemsPerPage)); i < j; i++) {
			this.elements.list.append('<li></li>');
		}
	}

	this.updateItems();

	// Clone items from last page and prepend them to the list
	this.elements.list.prepend(this.items.slice((this.options.itemsPerPage * (this.pageCount - 1))).clone());

	// Clone items from first page and append them to the list
	this.elements.list.append(this.items.slice(0, this.options.itemsPerPage).clone());
	this.updateItems();

	// Calculate widths
	this.itemWidth = Math.ceil(this.elements.clip.width() / this.options.itemsPerPage);
	this.items.width(this.itemWidth);
	this.elements.list.width(this.itemWidth * this.itemCount);

	this.elements.list.css('marginLeft', -(this.itemWidth * this.options.itemsPerPage));

	// Disable all hidden items to prevent them from getting keyboard focus
	this.disableHiddenLinks();
	
	// Remove link to view all
	this.elements.container.find('p.view-all').remove();

	// Add navigation links
	this.elements.nextLink = $('<a href="/" class="next"><span class="structural">Nästa</span></a>');
	this.elements.previousLink = $('<a href="/" class="previous"><span class="structural">Föregående</span></a>');
	this.elements.container.prepend(this.elements.nextLink, this.elements.previousLink);
	this.elements.nextLink.click(function (e) {
		e.preventDefault();
		t.nextPage();
	}).mousedown(function () {
		t.elements.nextLink.addClass('next-active');
	}).mouseup(function () {
		t.elements.nextLink.removeClass('next-active');
	});
	this.elements.previousLink.click(function (e) {
		e.preventDefault();
		t.previousPage();
	}).mousedown(function () {
		t.elements.previousLink.addClass('previous-active');
	}).mouseup(function () {
		t.elements.previousLink.removeClass('previous-active');
	});

	// Add paging links
	this.pager = new NetR.Pager({
		numberOfPages: this.pageCount,
		onPageShow: function (pager, link, pageNum) {
			t.showPage(pageNum);
		}
	});
	if(t.options.paging_position == "before") {
		this.elements.wrapper.prepend(this.pager.elements.container);
	} else {
		this.elements.wrapper.append(this.pager.elements.container);
	}
	this.pager.elements.container.wrap('<div class="paging-wrapper"><div class="paging-wrapper-inner cf"></div></div>');

	this.mode = NetR.Carousel.modes.IDLE;

};
NetR.Carousel.prototype = {
	updateItems: function () {
		this.items = this.elements.list.children('li');
		this.itemCount = this.items.size();
	},
	showPage: function (pageNum) {
		if (pageNum != this.activePage && pageNum <= this.pageCount && pageNum > 0) {
			this[pageNum < this.activePage ? 'goBack' : 'goForward'](Math.abs(pageNum - this.activePage));
		}
	},
	goForward: function (pages) {
		var t = this;
		pages = pages || 1;
		// we don't want to queue up animations, so first we check to see that we're idle
		if (this.mode != NetR.Carousel.modes.ANIMATING) {
			this.mode = NetR.Carousel.modes.ANIMATING;
			t.enableAllLinks();
			if(t.options.fading) {
				t.elements.container.fadeOut('fast', function () {
					t.elements.list.css('marginLeft', -(t.itemWidth * t.options.itemsPerPage) * (t.activePage + pages));
					if (t.activePage == t.pageCount) {
						t.activePage = pages;
						t.elements.list.css('marginLeft', -(t.itemWidth * t.options.itemsPerPage));
					} else {
						t.activePage = t.activePage + pages;
					}
					t.disableHiddenLinks();
					t.pager.showPage(t.activePage);
					t.mode = NetR.Carousel.modes.IDLE;
					t.elements.container.fadeIn('fast');
				});
			} else {
				t.elements.list.animate({'marginLeft': -(t.itemWidth * t.options.itemsPerPage) * (t.activePage + pages)}, 'slow', t.options.easing, function () {
					if (t.activePage == t.pageCount) {
						t.activePage = pages;
						t.elements.list.css('marginLeft', -(t.itemWidth * t.options.itemsPerPage));
					} else {
						t.activePage = t.activePage + pages;
					}
					t.disableHiddenLinks();
					t.pager.showPage(t.activePage);
					t.mode = NetR.Carousel.modes.IDLE;
				});
			}
		}
	},
	goBack: function (pages) {
		var t = this;
		pages = pages || 1;
		// we don't want to queue up animations, so first we check to see that we're idle
		if (this.mode != NetR.Carousel.modes.ANIMATING) {
			this.mode = NetR.Carousel.modes.ANIMATING;
			t.enableAllLinks();
			if(t.options.fading) {
				t.elements.container.fadeOut('fast', function () {
					t.elements.list.css('marginLeft', -(t.itemWidth * t.options.itemsPerPage) * (t.activePage - pages));
					if (t.activePage == 1) {
						t.activePage = t.pageCount;
						t.elements.list.css('marginLeft', -(t.itemWidth * t.options.itemsPerPage * t.pageCount));
					} else {
						t.activePage = t.activePage - pages;
					}
					t.disableHiddenLinks();
					t.pager.showPage(t.activePage);
					t.mode = NetR.Carousel.modes.IDLE;
					t.elements.container.fadeIn('fast');
				});
			} else {
				t.elements.list.animate({'marginLeft': -(t.itemWidth * t.options.itemsPerPage) * (t.activePage - pages)}, 'slow', t.options.easing, function () {
					if (t.activePage == 1) {
						t.activePage = t.pageCount;
						t.elements.list.css('marginLeft', -(t.itemWidth * t.options.itemsPerPage * t.pageCount));
					} else {
						t.activePage = t.activePage - pages;
					}
					t.disableHiddenLinks();
					t.pager.showPage(t.activePage);
					t.mode = NetR.Carousel.modes.IDLE;
				});
			}
		}
	},
	nextPage: function () {
		this.goForward(1);
	},
	previousPage: function () {
		this.goBack(1);
	},
	disableHiddenLinks: function () {
		var t = this;
		// Disable all items before this page
		this.items.slice(0, this.activePage * this.options.itemsPerPage).each(function () {
			$(this).css('visibility', 'hidden');
		});
		// Disable all items after this page
		this.items.slice((this.activePage + 1) * this.options.itemsPerPage).each(function () {
			$(this).css('visibility', 'hidden');
		});
	},
	enableAllLinks: function () {
		this.items.css('visibility', 'visible');
	}
};
NetR.Carousel.defaultOptions = {
	fading: false,
	itemsPerPage: 4,
	easing: 'easeOutCubic'
};
NetR.Carousel.modes = {
	IDLE: 0,
	ANIMATING: 1,
	LOADING: 2
};
