(function($) {
    function in_boundaries(value, min, max) {
	// Returns the value if it's between min and max.
	// Otherwise returns the boundary.
	return Math.max(min, Math.min(value, max));
    }


    function make_map(container) {
	var map = container.find('div.map');
	var items = container.find('div.map_popup');
	var current_item_id = 0;

	// The limits for items display.
	var boundaries = {'min_left': 0,
			  'max_left': map.width(),
			  'min_top': 0,
			  'max_top': map.height()};

	// By default, we do not play the animation.
	var paused = true;

	// We save all items coordinates in fake attributes so we won't
	// have to compute them again.
	items.each(function() {
	    var item = $(this);
	    var link = $('a#' + item.attr('id').replace('mp', 'mi'));
	    var link_position = link.position();
	    var item_height = item.outerHeight();
	    var item_width = item.outerWidth();
	    var link_height = link.outerHeight();
	    var link_width = link.outerWidth();
	    
	    var top, left;

	    // We look if there is place on the right of the link.
	    if (link_position['left'] + link_width < boundaries['max_left'] - item_width) {
		left = link_position['left'] + link_width;
	    } else {
		left = link_position['left'] - item_width;
	    }

	    // Same thing for the top.
	    if (link_position['top'] - item_height > boundaries['min_top']) {
		top = link_position['top'] - item_height;
	    } else {
		top = link_position['top'] + link_height;
	    }


	    item.attr('_map_saved_top', parseInt(top));
	    item.attr('_map_saved_left', parseInt(left));
	});


	function show_item(item) {
	    // Place an item at the correct position then shows it.
	    item.css({'top': item.attr('_map_saved_top') + 'px',
		      'left': item.attr('_map_saved_left') + 'px'});
	    item.fadeIn('slow');
	}

	function hide_item(item) {
	    // Hides the item then place it out of the map.
	    item.fadeOut('slow', function() {
		item.css({'left': '-500px',
			  'top': '-500px'})
	    });	
	}

	function animate() {
	    // Shows the current item, find the next one then hides it.
	    var item = $(items[current_item_id]);
	    show_item(item);

	    setTimeout(function() {
		hide_item(item);
		current_item_id ++
		if (current_item_id == items.length) {
		    current_item_id = 0;
		}

		if (!paused) {
		    animate();
		}
	    }, 1500);
	}

	function play() {
	    if (paused) {
		animate();
		paused = false;
	    }
	}

	function pause() {
	    paused = true;
	}

	if (items.length == 0) {
	    // Nothing to do.
	    return
	}

	if (items.length == 1) {
	    // Well, we won't make the image blink ...
	    // So we keep it visible everytime.
	    show_item($(items[0]));
	    return;
	}

	// Bindings.
	container.find('a.map_view').click(play);
	container.find('a.grid_view').click(play);


	container.find('a.mi').mouseenter(function() {
	    // When entering a link, we pause the animation and show the
	    // related item.
	    pause();
	    // Hide quickly the current item.
	    $(items[current_item_id]).hide().css({'top': '-500px', 'left': '-500px'});

	    $(this).find('img').attr('src', '/static/gfx/map_item_video_active.png');
	    show_item($('div#' + $(this).attr('id').replace('mi', 'mp')));
	});

	container.find('a.mi').mouseleave(function() {
	    $(this).find('img').attr('src', '/static/gfx/map_item_video.png');
	    hide_item($('div#' + $(this).attr('id').replace('mi', 'mp')));
	});

    }


    $.fn.map_animate = function() {
	this.each(function() {
	    make_map($(this));
	})
    }
})(jQuery)

