function init(carousel)
{
 	descendants = $('carousel_' + carousel).immediateDescendants()[CAROUSEL_ITEMS_INDEX].immediateDescendants();
 	
 	$('carousel_' + carousel + '_items').setStyle({ left: '0px' });
 	
 	carousel_animating_play_icon[carousel] = new Array(descendants.length);
	curr_left = 0;
	for (i=0; i<descendants.length; i++)
	{
		descendants[i].setStyle({ left: curr_left + 'px' });
		curr_left += parseFloat(descendants[i].getStyle('width') || '0') + CAROUSEL_ITEMS_SPACE[carousel];
		carousel_animating_play_icon[carousel][i] = false;
	}
	carousel_item_pos[carousel] = 0;

 	var slider_values = new Array(descendants.length - CAROUSEL_NR_OF_ITEMS[carousel] + 1);
 	for (i=0; i<slider_values.length; i++)
		slider_values[i] = i;
		
	if (sliders[carousel] != null)
		sliders[carousel].dispose();
	
	sliders[carousel] = new Control.Slider(
		'carousel_slider_tick_' + carousel, 'carousel_slider_track_' + carousel,
		{
			range: $R(0, (slider_values.length-1)),
			values: slider_values,
			onSlide: function(v)
			{
				onSlide(v, carousel);
			},
			onChange: function(v)
			{
				onSlide(v, carousel);
			}
		}
	);

	carousel_position_changed(carousel);
}
function onSlide(v, carousel)
{
	if (slider_current_values[carousel] == v) return;
    slider_last_value[carousel] = v;
    if (slider_last_value[carousel] != -1 && !moving[carousel])
		check_slider_last_value(carousel);
	
	carousel_position_changed(carousel, true);
}
function start_moving_carousel_forward(carousel)
{
	moving_forward[carousel] = true;
	carousel_forward(carousel);
}
function stop_moving_carousel_forward(carousel)
{
	moving_forward[carousel] = false;
}
function carousel_forward(carousel)
{
	if (moving[carousel]) return;
	
	items = $('carousel_' + carousel).immediateDescendants()[CAROUSEL_ITEMS_INDEX].immediateDescendants();
	if ((carousel_item_pos[carousel] + CAROUSEL_NR_OF_ITEMS[carousel]) >= items.length)
		return;
	
	item_width = parseFloat(items[carousel_item_pos[carousel]].getStyle('width') || '0') + CAROUSEL_ITEMS_SPACE[carousel];
	items_width = (items.length - carousel_item_pos[carousel])*item_width - CAROUSEL_ITEMS_SPACE[carousel];
	
	moving[carousel] = true;
	carousel_item_pos[carousel]++;
	carousel_position_changed(carousel);
	new Effect.Move('carousel_' + carousel + '_items', {duration: 0.5, x: -item_width, y: 0, mode: 'relative', transition: Effect.Transitions.linear,  
		afterFinish: function(effect)
		{ 
			moving[carousel] = false;
			if (moving_forward[carousel])
				carousel_forward(carousel);
		}
	});
}
function start_moving_carousel_back(carousel)
{
	moving_back[carousel] = true;
	carousel_back(carousel);
}
function stop_moving_carousel_back(carousel)
{
	moving_back[carousel] = false;
}
function carousel_back(carousel)
{
	if (moving[carousel]) return;
	
	items = $('carousel_' + carousel).immediateDescendants()[CAROUSEL_ITEMS_INDEX].immediateDescendants();
	if (carousel_item_pos[carousel] == 0) return;

	item_width = parseFloat(items[carousel_item_pos[carousel]].getStyle('width') || '0') + CAROUSEL_ITEMS_SPACE[carousel];

	moving[carousel] = true;
	carousel_item_pos[carousel]--;
	carousel_position_changed(carousel);
	new Effect.Move('carousel_' + carousel + '_items', {duration: 0.5, x: item_width, y: 0, mode: 'relative', transition: Effect.Transitions.linear, 
		afterFinish: function(effect)
		{ 
			moving[carousel] = false;
			if (moving_back[carousel])
				carousel_back(carousel);
		}
	});
}

function item_over(carousel, id, div)
{
	$('carousel_' + carousel + '_item_background_over_' + id).setStyle({
		visibility: 'visible'
    });

    if ($('carousel_' + carousel + '_item_' + id + '_play_icon') != null)
    {
	    if (!carousel_animating_play_icon[carousel][id])
		    animate_play_icon(carousel, id);
	    carousel_items_over[carousel] = id;
    }
}
function item_out(carousel, id, div)
{
	$('carousel_' + carousel + '_item_background_over_' + id).setStyle({
		visibility: 'hidden'
    });
    
    carousel_items_over[carousel] = -1;
}
function animate_play_icon(carousel, id)
{
	carousel_animating_play_icon[carousel][id] = true;
	new Effect.Opacity('carousel_' + carousel + '_item_' + id + '_play_icon', 
	{
		duration: 0.5, 
		from: 1.0, 
		to: 0.0, 
		transition: Effect.Transitions.linear,
		queue: {position: 'end', scope: 'animate_play_icon_' + carousel + '_' + id} 
	});  
	new Effect.Opacity('carousel_' + carousel + '_item_' + id + '_play_icon', 
	{
		duration: 0.5, 
		from: 0.0, 
		to: 1.0, 
		transition: Effect.Transitions.linear,
		queue: {position: 'end', scope: 'animate_play_icon_' + carousel + '_' + id},  
		afterFinish: function(effect) 
		{
			carousel_animating_play_icon[carousel][id] = false;
			if (carousel_items_over[carousel] == id)
				animate_play_icon(carousel, id);
		} 
	});  
}

function carousel_back_button_over(carousel, button)
{
	if (carousel_back_button_disabled[carousel]) return;
	
	carousel_button_over(button);
	start_moving_carousel_back(carousel);
}
function carousel_back_button_out(carousel, button)
{
	if (carousel_back_button_disabled[carousel]) return;
	
	carousel_button_out(button);
	stop_moving_carousel_back(carousel);
}
function carousel_forward_button_over(carousel, button)
{
	if (carousel_forward_button_disabled[carousel]) return;
	
	carousel_button_over(button);
	start_moving_carousel_forward(carousel);
}
function carousel_forward_button_out(carousel, button)
{
	if (carousel_forward_button_disabled[carousel]) return;
	
	carousel_button_out(button);
	stop_moving_carousel_forward(carousel);
}
function carousel_button_over(button)
{
	$(button).setOpacity(0.7);
	$(button).setStyle({
		cursor: 'pointer'
	});
}
function carousel_button_out(button)
{
	$(button).setOpacity(1.0);
	$(button).setStyle({
		cursor: 'default'
	});
}
function carousel_back_button_disable(button, carousel)
{
	carousel_back_button_disabled[carousel] = true;
	carousel_button_disable(button, carousel);
}
function carousel_forward_button_disable(button, carousel)
{
	carousel_forward_button_disabled[carousel] = true;
	carousel_button_disable(button, carousel);
}
function carousel_button_disable(button, carousel)
{
	$(button).setOpacity(0.7);
	$(button).setStyle({
		cursor: 'default'
	});
}
function carousel_back_button_enable(button, carousel)
{
	carousel_back_button_disabled[carousel] = false;
	carousel_button_enable(button, carousel);
}
function carousel_forward_button_enable(button, carousel)
{
	carousel_forward_button_disabled[carousel] = false;
	carousel_button_enable(button, carousel);
}
function carousel_button_enable(button, carousel)
{
	$(button).setOpacity(1.0);
	$(button).setStyle({
		cursor: 'pointer'
	});
	carousel_back_button_disabled[carousel] = false;
}
function carousel_position_changed(carousel, called_from_slider)
{
	called_from_slider = called_from_slider || false;

	items = $('carousel_' + carousel).immediateDescendants()[CAROUSEL_ITEMS_INDEX].immediateDescendants();
	
	if ((carousel_item_pos[carousel] + CAROUSEL_NR_OF_ITEMS[carousel]) >= items.length)
	{
		if (!carousel_forward_button_disabled[carousel])
			carousel_forward_button_disable('carousel_' + carousel + '_forward_button', carousel);
	}
	else
	{
		if (carousel_forward_button_disabled[carousel])
			carousel_forward_button_enable('carousel_' + carousel + '_forward_button', carousel);
	}
	if (carousel_item_pos[carousel] == 0)
	{
		if (!carousel_back_button_disabled[carousel])
			carousel_back_button_disable('carousel_' + carousel + '_back_button', carousel);
	}
	else
	{
		if (carousel_back_button_disabled[carousel])
			carousel_back_button_enable('carousel_' + carousel + '_back_button', carousel);
	}

	slider_current_values[carousel] = carousel_item_pos[carousel]; //to prevent the event handlers from doing what they do ;)
	if (!called_from_slider)
		sliders[carousel].setValue(carousel_item_pos[carousel]);
}
function check_slider_last_value(carousel)
{
	slider_value = slider_last_value[carousel];
	slider_last_value[carousel] = -1;

	items = $('carousel_' + carousel).immediateDescendants()[CAROUSEL_ITEMS_INDEX].immediateDescendants();
	new_pos = slider_value;

	item_width = parseFloat(items[carousel_item_pos[carousel]].getStyle('width') || '0') + CAROUSEL_ITEMS_SPACE[carousel];
	width = item_width * (new_pos - carousel_item_pos[carousel]);

	moving[carousel] = true;
	new Effect.Move('carousel_' + carousel + '_items', {duration: 0.5, x: -width, y: 0, mode: 'relative', queue: 'carousel_' + carousel + '_items_moving', 
		afterFinish: function(effect)
		{ 
			moving[carousel] = false;
			if (slider_last_value[carousel] != -1)
				check_slider_last_value(carousel);
		}
	});
	carousel_item_pos[carousel] = new_pos;
}