function Carousel() {
	this.slides = new Array();
	this.slidesLoaded = 0;
	this.interval = 0;
	this.locked = false;
	this.position = 0;
	this.target = 0;
	this.viewRange = 2.2;
	this.viewWidth = 316;
	this.viewHeight = 170;
	this.farScale = 0.5;
	this.nearScale = 1;
	this.mouseX = 0;
}

Carousel.prototype.init = function (targetId) {
	
	this.locked = true;
	
	this.target = Math.floor(this.slides.length * 0.5); 
	
	var target = $('#' + targetId)[0];
	var list = document.createElement('ul');
	
	for (var i in this.slides) {
		slide = this.slides[i];
		var item = document.createElement('li');
		var link = document.createElement('a');
		list.appendChild(item);
		item.appendChild(link);
		link.setAttribute('href', slide.link);
		link.appendChild(slide.element);
	}
	
	target.appendChild(list);
	
	if (this.slidesLoaded == this.slides.length)
		this.start();
	
	$('#fondSlide #infoBox #bottles').mousemove(function (event) {
		var allWidth = $('#fondSlide #infoBox #bottles').width();
		var oneWidth = allWidth / carousel.slides.length;
		var localX = event.pageX - $('#fondSlide #infoBox #bottles').offset().left;
		carousel.target = Math.min(Math.max(localX / oneWidth - 0.5, 0), carousel.slides.length - 1); 
		//console.log(localX / oneWidth);
	});
	
	$('#fondSlide #' + targetId).mousemove(function (event) {
		moveIt = true;
		var width = $('#fondSlide #' + targetId).width();
		cMouseDX = (event.pageX - $('#fondSlide #' + targetId).offset().left) - width * 0.5;
		var reduced = Math.max(Math.abs(cMouseDX) - 20, 0);
		cMouseDX = cMouseDX < 0 ? -reduced : reduced ;
	});
	
	$('#fondSlide #' + targetId).mouseout(function () {
		moveIt = false;
	});
}

Carousel.prototype.addSlide = function (image, link) {
	if (!this.locked)
		this.slides.push(new Slide(this, image, link));
}

Carousel.prototype.setPosition = function (value) {
	this.position = value;
	this.arrangeSlides();
}

Carousel.prototype.slideLoaded = function () {
	this.slidesLoaded++;
	if (this.slidesLoaded == this.slides.length && this.locked) {
		this.start();
	}
}

Carousel.prototype.start = function () {
	//console.log('Start!');
	this.timeloop();
}

Carousel.prototype.timeloop = function () {
	//if (this.position < 2.5)
		this.interval = setTimeout(delegate(this, this.timeloop), 1000 / 60);
	//this.position = (this.position + 0.02) % (this.slides.length - 1);
	//this.viewRange = (this.viewRange + 0.02) % (10);
	var dist = this.position - this.target;
	this.position -= dist * 0.2;
	this.arrangeSlides();
	if (moveIt) {
		carousel.target += cMouseDX * 0.001;
		carousel.target = Math.min(Math.max(carousel.target, 0), carousel.slides.length);
	}
}

Carousel.prototype.arrangeSlides = function () {
	for (var i in this.slides) {
		var slide = this.slides[i];
		var distance = Math.abs(i - this.position);
		
		if (distance <= this.viewRange) {
			
			slide.setHidden(false);
			
			var distFactor = Math.sin(Math.PI * 0.5 * (1 - (distance / this.viewRange)));
			var positionFactor = (i - (this.position - this.viewRange)) / (this.viewRange * 2);
				
			slide.setScale(this.farScale + (this.nearScale - this.farScale) * distFactor);
			slide.setOpacity(distFactor);
			var newX = this.viewWidth * positionFactor - slide.getWidth() * 0.5;
			var fromCenter = this.viewWidth * 0.5 - newX;
			newX = this.viewWidth * 0.5 - fromCenter * (slide.scale * 0.4 + 0.7);
			var newY = this.viewHeight * 0.5 - slide.getHeight() * 0.5;
			slide.setPosition(newX, newY);
			
		} else {
			
			slide.setHidden(true);
		}
	}
	
	var zSorted = this.slides.slice(0);
	zSorted.sort(function (a, b) {
		if (a.scale < b.scale)
			return -1;
		else if (a.scale > b.scale)
			return 1;
		else
			return 0;
	});
	
	for (var i in zSorted) {
		var slide = zSorted[i];
		slide.setZIndex(i);
	}
}

/**
 * Delegate function copied from:
 * http://developingwithstyle.blogspot.com/2010/04/javascript-delegate-and-extending.html
 */
function delegate(context, func){
	//check to see if the there are more parameters than the context and func. if there is, strip the first two arguments and apply the context and remaining arguments to the func
	if(arguments.length > 2)
	{
		var args = [];
		for(var n = 2; n < arguments.length; ++n) args.push(arguments[n]);
		return function() { return func.apply(context, args); }
	}
	//if there arent more than two arguments, just invoke the func with the context
	else
		return function() { return func.call(context); }
}
