/***
 * qCarousel
 * Copyright 2010 QForma
 * 
 * TODO: store action when sliding. Already storing activeAnimations
 */


// Store the active animations outside the object's scope
var qCarouselActiveAnimations = 0;

/**
 * Constructor
 * Sets up the settings
 */
function qCarousel(dataContainer, settings)
{
	this.container;
	this.dataContainer 	 = dataContainer;
	this.activeAnimations = 0;
	
	this.settings		 		= {};
	this.settings.items  		= 5;
	this.settings.containerWidth  = 730;
	this.settings.containerHeight = 500;
	this.settings.imageWidth 	= 260;
	this.settings.imageHeight 	= 360;
	
	this.settings.props = {
		'main'		: {
			'top'		: 50+'px',
			'left'		: Math.round( this.settings.containerWidth / 2 - this.settings.imageWidth / 2 )+'px',
			'width'		: this.settings.imageWidth,
			'height'	: this.settings.imageHeight,
			'opacity'	: 1.0
		},
		'next-1'	: {
			'top'		: 50 + Math.round( (this.settings.imageHeight - Math.round( this.settings.imageHeight * 0.6 ))  / 2)+'px',
			'left'		: Math.round( this.settings.containerWidth / 2  +  this.settings.imageWidth / 2 )+'px',
			'width'		: Math.round( this.settings.imageWidth * 0.6 ),
			'height'	: Math.round( this.settings.imageHeight * 0.6 ),
			'opacity'	: 0.7
		},
		'previous-1': {
			'top'		: 50 + Math.round( (this.settings.imageHeight - Math.round( this.settings.imageHeight * 0.6 ))  / 2)+'px',
			'left'		: Math.round( this.settings.containerWidth / 2  -  this.settings.imageWidth  -  20 )+'px',
			'width'		: Math.round( this.settings.imageWidth * 0.6 ),
			'height'	: Math.round( this.settings.imageHeight * 0.6 ),
			'opacity'	: 0.7
		},
		'next-2'	: {
			'top'		: 50 + Math.round( (this.settings.imageHeight - Math.round( this.settings.imageHeight * 0.3 ))  / 2)+'px',
			'left'		: this.settings.containerWidth-100 +'px',
			'width'		: Math.round( this.settings.imageWidth * 0.3 ),
			'height'	: Math.round( this.settings.imageHeight * 0.3 ),
			'opacity'	: 0.3
		},
		'previous-2'	: {
			'top'		: 50 + Math.round( (this.settings.imageHeight - Math.round( this.settings.imageHeight * 0.3 ))  / 2)+'px',
			'left'		: 40 +'px',
			'width'		: Math.round( this.settings.imageWidth * 0.3 ),
			'height'	: Math.round( this.settings.imageHeight * 0.3 ),
			'opacity'	: 0.3
		},
		// Preload positions
		'next-3'	: {
			'top'		: 50 + Math.round(this.settings.imageHeight / 2)+'px',
			'left'		: this.settings.containerWidth - 20 +'px',
			'width'		: 0,
			'height'	: 0,
			'opacity'	: 0.0
		},
		'previous-3': {
			'top'		: 50 + Math.round(this.settings.imageHeight / 2)+'px',
			'left'		: 0,
			'width'		: 0,
			'height'	: 0,
			'opacity'	: 0.0
		}
	};
};


/**
 * Initialize
 * Starts the carousel in the container & initializes from starting position
 */
qCarousel.prototype.initialize = function(selector)
{
	this.container = jQuery(selector);

	// Add main image
	this.setImage(this.dataContainer.getImage( this.dataContainer.current() ), 'main');
	
	// Add side images + preload one level extra
	for (var i=1; i <= this.getDistance() + 1; i++)
	{
		this.setImage(this.dataContainer.getImage( this.dataContainer.next(i) ), 		'next', 		i);
		this.setImage(this.dataContainer.getImage( this.dataContainer.previous(i) ), 	'previous', 	i);
	}
}


/**
 * Determines the distance of this carousel
 */
qCarousel.prototype.getDistance = function()
{
	return Math.floor( this.settings.items / 2 );
}


/**
 * Adds an image to the scene
 */
qCarousel.prototype.setImage = function(img, type, distance)
{
	if (distance == undefined)
		distance = 0;
	
	img.removeClass(); //Remove all classes
	img.addClass('carousel-'+type);
	img.addClass('carousel-'+type+'-'+distance);
	
	var typeKey = (distance > 0)
		?	type +'-'+ distance
		:	type;
	
	if (typeKey in this.settings.props)
	{
		img.css( this.settings.props[typeKey] );
		this.container.append(img);
		
		var self = this;
		$(img).click(function(){
			self.handleClick(this);
		});
	}
	//else: image is preloaded without attaching it to a DOM object
}


/**
 * Called when clicked on an element
 * Manages the animation and subsequent preloading
 */
qCarousel.prototype.handleClick = function(e)
{
	// Only handle clicks when there are no qCarousel animations
	if (qCarouselActiveAnimations > 0)
		return;
	
	// Determine what the move will be
	var classes = $(e).attr('className').split(' ');
	for (var i=0; i<classes.length; i++)
	{
		var typeArgs = classes[i].split('-');
		if (typeArgs.length > 1  &&  typeArgs[0] == 'carousel')
		{
			if (typeArgs.length == 3)
			{
				var direction = typeArgs[1];
				var distance  = typeArgs[2];
			}
			else if (typeArgs.length == 2)
				var mode = typeArgs[1];
		}
	}
	
	// Launch fancybox for main image
	if (mode  &&  mode == 'main')
		return jQuery.fancybox({
			'type'		: 'image',
			'autoScale'	: false,
			'content'	: $(e).attr('src').replace(/\.png$/i, '-big.jpg')
		});
	
	// Do nothing if direction & distance isn't working
	else if (!direction || !distance)
		return false;
	
	
	//Otherwise: do carousel animation
	var opposite = (direction == 'next')  ?  'previous'  :  'next';
	
	// Remove unused preloader
	$('.carousel-'+ opposite +'-'+ parseInt(this.getDistance()+1)).remove();
	
	// Animate main image
	this.animate('main', opposite+'-1');
	this.animate(direction+'-1', 'main');
	
	// Animate others
	for (var i=1; i <= this.getDistance(); i++)
	{
		this.animate(direction+'-'+(i+1), direction+'-'+i);
		this.animate(opposite+'-'+i, opposite+'-'+(i+1));
	}
	
	// Add preload image
	(direction == 'next')  ?  this.dataContainer.setNext()  :  this.dataContainer.setPrevious();
	var preloadDistance = parseInt( this.getDistance() + 1 );
	this.setImage(
		this.dataContainer.getImage(
			this.dataContainer[ direction ]( preloadDistance )
		), direction, preloadDistance
	);
}


/**
 * Handles the animation of an element.
 * When the animation is completed, the classnames are updated
 */
qCarousel.prototype.animate = function(className, to)
{
	var object = $('.carousel-'+ className);
	qCarouselActiveAnimations++;
	
	object.animate(this.settings.props[ to ], 1000, function(){
		object.removeClass();
		object.addClass('carousel-'+to);
		
		var specific = to.split('-');
		if (specific.length == 2)
			object.addClass('carousel-'+ specific[0]);
		
		qCarouselActiveAnimations--;
	});
}

