/*
 * gallery.js (V.1.0.1)
 * An horizontal scrolling gallery with custom effects
 * @author : Jean Semere (Baggage Claim)
 *
 * You have no right to use or redistribute this code unless Baggage Claim SARL
 * authorizes you to do so.
 *
 */

Gallery = Class.create();
Gallery.prototype =
{
	initialize: function(container, scroller, zoomer, options)
	{
		this.busy = false;
		this.tbusy = false;
		this.xTarget = 0;
		this.container = $(container);
		this.scroller = $(scroller);
		this.zoomer = $(zoomer);
		this.browser = new Browser(true);
		this.elementsAreVisible = true;
		options = options || {};
		this.controller = $(options.controller) || false;
		this.controlContainer = $(options.controlContainer) || $("controlContainer");
		this.elementType = options.elementType || "img";
		this.elements = this.scroller.getElementsBySelector(this.elementType);
		this.unselectedClass = options.unselectedClass || "unselectedImage";
		this.selectFirst = options.selectFirst || true;
		this.currentElement = false;
		for (i=0; i<this.elements.length; i++)
		{
			this.elements[i] = $(this.elements[i]);
			this.elements[i].addClassName(this.unselectedClass);
			Event.observe(this.elements[i], 'click', this.dispatch.bindAsEventListener(this), false);
		}
		if (this.controller)
		{
			this.controls = this.controller.getElementsBySelector(this.elementType);
			for (i=0; i<this.controls.length; i++)
			{
				this.controls[i] = $(this.controls[i]);
				Event.observe(this.controls[i], 'click', this.selectWithThumb.bindAsEventListener(this), false);
			}
			this.controlsNumber = this.controls.length;
			this.controlsStarts = new Array();
			this.controlsEnds = new Array();
			this.controlsPages = this.controller.getElementsBySelector("div");
			this.reverseControls = new Array();
			for (i=0; i<this.controlsPages.length; i++)
			{
				this.controlsPages[i] = $(this.controlsPages[i]);
				this.controlsStarts[i] = this.controlsPages[i].id.split("_")[2];
				this.controlsEnds[i] = this.controlsPages[i].id.split("_")[3];
				this.reverseControls[this.controlsPages[i].id] = i;
			}
			this.controlsPages = this.controlsPages.length;
			this.currentPage = 0;
			$("galleryTotal").innerHTML = this.controlsNumber.toString();
			$("galleryPage").innerHTML = this.controlsStarts[this.currentPage].toString() + " - " + this.controlsEnds[this.currentPage].toString();
		}
		if (this.selectFirst)
			this.select(this.elements[0]);
		Event.observe(window, 'resize', this.move.bindAsEventListener(this), false);
	},
	
	selectWithThumb: function(event)
	{
		thumb = Event.findElement(event, this.elementType);
		id = thumb.id.split("_").last();
		element = $(id);
		if (element != null)
			this.select(element);
	},
	
	unblockThumbs: function()
	{
		this.tbusy = false;
	},
	
	goToThumbPage: function(parentNode)
	{
		target = this.reverseControls[parentNode.id];
		if (target == this.currentPage)
			return;
		else if (target < this.currentPage)
			this.goToPreviousPage();
		else
			this.goToNextPage();
	},
	
	goToNextPage: function()
	{
		if (this.tbusy)
		{
			this.goToNextPage.bind(this).delay(0.1);
			return;
		}
		if (this.currentPage < this.controlsPages - 1)
		{
			this.tbusy = true;
			this.currentPage++;
			$("galleryPage").innerHTML = this.controlsStarts[this.currentPage].toString() + " - " + this.controlsEnds[this.currentPage].toString();
			new Effect.Move(this.controller, { x: -this.controlContainer.getWidth(), mode: "relative", afterFinish: this.unblockThumbs.bind(this) });
		}
	},
	
	goToPreviousPage: function()
	{
		if (this.tbusy)
		{
			this.goToPreviousPage.bind(this).delay(0.1);
			return;
		}
		if (this.currentPage > 0)
		{
			this.tbusy = true;
			this.currentPage--;
			$("galleryPage").innerHTML = this.controlsStarts[this.currentPage].toString() + " - " + this.controlsEnds[this.currentPage].toString();
			new Effect.Move(this.controller, { x: this.controlContainer.getWidth(), mode: "relative", afterFinish: this.unblockThumbs.bind(this) });
		}
	},
	
	dispatch: function(event)
	{
		element = Event.findElement(event, this.elementType);
		if (this.currentElement == element)
			this.zoom();
		else
			this.select(element);
	},
	
	zoom: function()
	{	
		node = Builder.node('img', {
			id: "zoomImage",
			style: "position: absolute; display: none; z-index: 200; border: 2px solid white; top: "+this.currentElement.cumulativeOffset().top+"px; left: "+this.currentElement.cumulativeOffset().left+"px",
			src: this.currentElement.src,
			height: parseInt(this.currentElement.height)+"px",
			width: parseInt(this.currentElement.width)+"px"
		});
		this.zoomer.appendChild(node);
		
		h = this.browser.height - 40;
		w = this.browser.width - 40;
		hratio = h / parseInt(this.currentElement.height);
		wratio = w / parseInt(this.currentElement.width);
		
		if (hratio < wratio)
		{
			percent = hratio * 100;
			leftOffset = (w - hratio*this.currentElement.width) / 2;
			$("zoomImage").show();
			$("galleryCaption").hide();
			$("galleryContainer").hide();
			$("controlTop").hide();
			$("breadcrumbs").hide();
			$("menu").hide();
			$("menuToggleButton").hide();
			new Effect.Parallel([
				new Effect.Scale("zoomImage", percent, { sync: true }),
				new Effect.Move("zoomImage", { sync: true, x: leftOffset+10, y: 15, mode: "absolute" })
			], { duration: 1 });
		}
		else
		{
			percent = wratio * 100;
			topOffset = (h - wratio*this.currentElement.height) / 2;
			$("zoomImage").show();
			$("galleryCaption").hide();
			$("galleryContainer").hide();
			$("controlTop").hide();
			$("breadcrumbs").hide();
			$("menu").hide();
			$("menuToggleButton").hide();
			new Effect.Parallel([
				new Effect.Scale("zoomImage", percent, { sync: true }),
				new Effect.Move("zoomImage", { sync: true, x: 15, y: topOffset+10, mode: "absolute" })
			], { duration: 1 });
		}
		new Effect.Appear("transparentGrey", { to: 0.4 });
		Event.observe($("transparentGrey"), 'click', this.unzoom.bindAsEventListener(this), false);
		Event.observe($("zoomImage"), 'click', this.unzoom.bindAsEventListener(this), false);
	},
	
	hideZoomer: function()
	{
		this.zoomer.innerHTML = "&nbsp;";
	    $("galleryCaption").show();
	    $("galleryContainer").show();
	    $("controlTop").show();
		$("breadcrumbs").show();
		if (!this.elementsAreVisible)
			$("menu").show();
		$("menuToggleButton").show();
	},
	
	unzoom: function()
	{
		new Effect.Fade("transparentGrey", {
			afterFinish: function()
			{
				$("transparentGrey").hide();
			}
		});
		new Effect.Fade("zoomImage", {
			afterFinish: this.hideZoomer.bind(this)
		});
	},
	
	setStyleAndAppear: function()
	{
		$("galleryCaption").setStyle({
			left: this.currentElement.cumulativeOffset().left + "px",
			top: this.currentElement.cumulativeOffset().top - 18 + "px"
		});
		new Effect.Appear("galleryCaption", {duration: 0.4});
	},
	
	activate: function()
	{
		this.currentElement.removeClassName(this.unselectedClass);
		alt = this.currentElement.readAttribute('alt');
		if (alt)
			alt = alt.split(" :: ");
		else
		{
			this.busy = false;
			return;
		}
		$("galleryTitle").innerHTML = alt.first().toUpperCase();
		$("galleryOtherCaption").innerHTML = alt.last();
		$("galleryCaption").setStyle({
			left: this.currentElement.cumulativeOffset().left + "px",
			top: this.currentElement.cumulativeOffset().top - 18 + "px"
		});
		if (!this.elementsAreVisible)
		{
			this.currentElement.setStyle({visibility: "visible"});
			new Effect.Appear(this.scroller, {
				duration: 0.5
			});
			this.setStyleAndAppear.bind(this).delay(0.1);
		}
		else
			new Effect.Appear("galleryCaption", {duration: 0.5});
		this.busy = false;
	},
	
	moveCaption: function()
	{
		new Effect.Move("galleryCaption", {
			x: this.currentElement.cumulativeOffset().left,
			y: this.currentElement.cumulativeOffset().top - 18,
			mode: "absolute"
		});
	},
	
	move: function()
	{
		xTarget = (this.container.getWidth() - this.currentElement.getWidth()) / 2 - this.currentElement.positionedOffset().left;
		if (this.xTarget == xTarget)
			return;
		this.xTarget = xTarget;
		this.mouseMove = new Effect.Move(this.scroller, {
			x: xTarget,
			mode: "absolute",
			afterFinish: this.moveCaption.bind(this)
		});
	},
	
	select: function(element)
	{
		element = $(element);
		Event.observe(element, 'load', this.move.bindAsEventListener(this), false);
		if (this.currentElement)
		{
			this.currentElement.addClassName(this.unselectedClass);
			if (!this.elementsAreVisible)
				this.currentElement.setStyle({visibility: "hidden"});
			if (this.controller)
				$("control_" + this.currentElement.id).removeClassName("controlActive");
		}
		$("galleryCaption").setStyle({
			opacity: 0
		});
		this.currentElement = element;
		if (this.controller)
		{
			$("control_" + this.currentElement.id).addClassName("controlActive");
			parentNode = $("control_" + this.currentElement.id).ancestors().first();
			this.goToThumbPage(parentNode);
		}
		xTarget = (this.container.getWidth() - this.currentElement.getWidth()) / 2 - this.currentElement.positionedOffset().left;
		this.busy = true;
		if (!this.elementsAreVisible)
			this.scroller.hide();
		scrollDuration = 1;
		if (!this.elementsAreVisible)
			scrollDuration = 0;
		if (this.selectMove)
			this.selectMove.cancel();
		this.selectMove = new Effect.Move(this.scroller, {
			x: xTarget,
			mode: "absolute",
			duration: scrollDuration,
			afterFinish: this.activate.bind(this)
		});
	},
	
	hideOthers: function()
	{
		for (i=0; i<this.elements.length; i++)
		{
			if (this.elements[i] != this.currentElement)
				$(this.elements[i]).setStyle({visibility: "hidden"});
		}
	},
	
	showAll: function()
	{
		for (i=0; i<this.elements.length; i++)
		{
			$(this.elements[i]).setStyle({visibility: "visible"});
		}
	},
	
	toggleVisibility: function()
	{
		if (this.elementsAreVisible)
		{
			this.hideOthers();
			this.elementsAreVisible = false;
		}
		else
		{
			this.showAll();//.bind(this).delay(1);
			this.elementsAreVisible = true;
		}
	}
};

