/*
 * The MIT License
 *
 * Copyright (c) <2010> <Richard Downes richard.downes@gmail.com>
 * CSS and HTML contributed by Jamie Stanton <jamie.stanton@gmail.com> while working with Evolution-e (www.evolution-e.com)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

(function() {

var $ = document.id;

this.FSGallery = new Class({

	Implements: [Events, Options],

	options: {
		container: null,	/* The outer container of the gallery, either an id or an element */
		imageList: null,	/* The unordered list (ul) element containing the film strip, either an id or an element */
		forwardButton: null,/* The button that makes it go forward, either an id or an element */
		backButton: null,	/* The button that makes it go back, either an id or an element */
		imageElement: null,	/* The actual image element, either an id or an element*/
		dimensions: {
			/*
				TODO: If the values in the dimensions are not valid (i.e. undefined, zero or null)
				then auto-configure them from the current values
			*/
			selected: {
				"width": 126,
				"height": 94,
				"padding-top": 10
			},
			normal: {
				"width": 126,
				"height": 94,
				"padding-top": 10
			}
		}
	},

	// the unordered list element containing the file film strip images
	_imageList: null,

	// the button to make it move forwards
	_forwardButton: null,

	// the button to make it move backwards
	_backButton: null,

	initialize: function(options)
	{
		this.setOptions(options);
		this._container = $(this.options.container);
		this._imageList = $(this.options.imageList);
		this._forwardButton = $(this.options.forwardButton);
		this._backButton = $(this.options.backButton);
		this._imageElement = $(this.options.imageElement);

		var images = this._imageList.getElements("li a img");
		var counter = 0;
		// cycle through the images, add the click event, make sure the primary image has an initial size (makes it easier)
		// and update the main image to the second image in the list
		images.each(function(img) {
			img.addEvent("click", this.imageClickEvent.bindWithEvent(this));
			var dimensions = this.options.dimensions.normal;
			if (counter == 1)
			{
				var url = img.getParent("a").getProperty("href");
				this.updateImage(url);
				this.updateTabText(img.getProperty("alt"), img.getParent("a").getParent("li").getFirst("span").get("text"));
				/*dimensions = this.options.dimensions.selected;*/
				img.getParent("a").getParent("li").addClass("selected");
			}
			img.setStyle("width", dimensions.width + "px");
//			img.setStyle("height", dimensions.height + "px");
			img.getParent("li").setStyle("padding-top", dimensions["padding-top"]);
			counter++;
		}, this);

		this._forwardButton.addEvent("click", this._forwardClickEvent.bind(this));
		this._backButton.addEvent("click", this._backClickEvent.bind(this));
		// make sure the image list has a default margin-left property
		this._imageList.setStyle("margin-left", "0px");
		this.setImageListWidth();
	},

	forward: function()
	{
		// we can safely re-enable the back button when moving forward
		this._backButton.removeClass("disabled");
		// current margin left + width of the restricted part is equal to the overall width of the carousel
		// the current left position of the image list
		var curLeft = parseInt(this._imageList.getStyle("margin-left"), 10);
		// find the size of a normal image
		var listItem = this._imageList.getFirst("li");
		coords = listItem.getCoordinates();
		var width = coords.width;

		// to move forward we need to scale the currently selected item down and scale the item immediately to its left up
		/* is this still the case? The above comment may be incorrect for planit */
		var curItem = this._imageList.getFirst("li.selected");
		var nextItem = curItem.getNext("li");

		// get the image elements
		var curImage = curItem.getFirst("a").getFirst("img");
		var nextImage = nextItem.getFirst("a").getFirst("img");

		/*
		 * if next image has no next sibling then we need to move the filmstrip to the right by whatever the
		 * width of a single item is, then move the first item from the start position and pop it onto the end
		 * of the film strip, this way we have a conveyor belt effect.
		 */
		if (!nextItem.getNext("li") || nextItem.getNext("li") == null)
		{
			curLeft = (curLeft + width);
			this._imageList.setStyle("margin-left", curLeft);
			var firstItem = this._imageList.getFirst("li");
			firstItem.inject(this._imageList, "bottom");
		}

		// get the url for the next image and update it
		var url = nextImage.getParent("a").getProperty("href");
		this.updateImage(url);
		this.updateTabText(nextImage.getProperty("alt"), nextImage.getParent("a").getParent("li").getFirst("span").get("text"));

		var elementArray = [this._imageList, curItem, curImage, nextItem, nextImage];
		var sdimensions = this.options.dimensions.selected;
		var ndimensions = this.options.dimensions.normal;
		var transitions = {
			'0': {'margin-left': [curLeft, (curLeft - coords.width)]}
			/*'1': {'padding-top': [sdimensions["padding-top"], ndimensions["padding-top"]]},
			'2': {'width': [sdimensions.width, ndimensions.width], 'height': [sdimensions.height,ndimensions.height]},
			'3': {'padding-top': [ndimensions["padding-top"], sdimensions["padding-top"]]},
			'4': {'width': [ndimensions.width,sdimensions.width], 'height': [ndimensions.height,sdimensions.height]}*/
		}
		var fx = new Fx.Elements(elementArray, {duration: "short", transition: Fx.Transitions.Sine.easeOut, onComplete: function() {
			curItem.removeClass("selected");
			nextItem.addClass("selected");
			curItem.set("padding", "2px");
			// get the next item and pre-load its image, if there is a next item
/*			var img = nextItem.getNext("li")
			if (img)
			{
				img = img.getFirst("a");
				new Asset.image(img.getProperty("href"));
			}*/
		}});
		fx.start(transitions);
		// check if we need to disable the button
		var marginLeft = parseInt(this._imageList.getStyle("margin-left"), 10);
		var restrictedWidth = this._container.getCoordinates().width;
		if (Math.abs(marginLeft) + restrictedWidth >= this._imageList.getCoordinates().width)
		{
//			this._forwardButton.addClass("disabled");
//			this._forwardButton.removeEvents("click");
		}
		this.fireEvent("forward", this);
	},

	back: function()
	{
		if (this._forwardButton.hasClass("disabled"))
		{
			this._forwardButton.removeClass("disabled");
//			this._forwardButton.addEvent("click", this._forwardClickEvent.bind(this));
		}
		// when current margin left is zero or more then set it to zero and disable the back button
		var curLeft = parseInt(this._imageList.getStyle("margin-left"), 10);
		// find the size of an image
		var listItem = this._imageList.getFirst("li");
		coords = listItem.getCoordinates();
		var width = coords.width;

		// to move back we need to scale the currently selected item down and scale the item immediately to its left up
		var curItem = this._imageList.getFirst("li.selected");
		var nextItem = curItem.getPrevious("li");

		/*
		 * if next image has no next sibling then we need to move the filmstrip to the right by whatever the
		 * width of a single item is, then move the first item from the start position and pop it onto the end
		 * of the film strip, this way we have a conveyor belt effect.
		 */
		if (!nextItem.getPrevious("li") || nextItem.getPrevious("li") == null)
		{
			curLeft = (curLeft - width);
			this._imageList.setStyle("margin-left", curLeft);
			var lastItem = this._imageList.getLast("li");
			lastItem.inject(this._imageList, "top");
		}

		// get the image elements
		var curImage = curItem.getFirst("a").getFirst("img");
		var nextImage = nextItem.getFirst("a").getFirst("img");
		var dimensions = {
			width: nextImage.getCoordinates().width,
			height: nextImage.getCoordinates().height,
			selectedWidth: curImage.getCoordinates().width,
			selectedHeight: curImage.getCoordinates().height
		};
		// get the url for the next image and update it
		var url = nextImage.getParent("a").getProperty("href");
		this.updateImage(url);
		this.updateTabText(nextImage.getProperty("alt"), nextImage.getParent("a").getParent("li").getFirst("span").get("text"));
		var elementArray = [this._imageList, curItem, curImage, nextItem, nextImage];
		var sdimensions = this.options.dimensions.selected;
		var ndimensions = this.options.dimensions.normal;
		var transitions = {
			'0': {'margin-left': [curLeft, (curLeft + coords.width)]}
/*			'1': {'padding-top': [sdimensions["padding-top"], ndimensions["padding-top"]]},
			'2': {'width': [sdimensions.width, ndimensions.width], 'height': [sdimensions.height,ndimensions.height]},
			'3': {'padding-top': [ndimensions["padding-top"], sdimensions["padding-top"]]},
			'4': {'width': [ndimensions.width,sdimensions.width], 'height': [ndimensions.height,sdimensions.height]}*/
		}
		var fx = new Fx.Elements(elementArray, {duration: "short", transition: Fx.Transitions.Sine.easeOut, onComplete: function() {
			curItem.removeClass("selected");
			nextItem.addClass("selected");
		}});
		fx.start(transitions);
		// check if we need to disable the button
		if (curLeft == 0)
		{
			this._backButton.addClass("disabled");
//			this._backButton.removeEvents("click");
		}
		this.fireEvent("back", this);
	},

	setImageListWidth: function()
	{
		var selected = this._imageList.getFirst("li.selected");
		var coords = selected.getCoordinates();
		var selectedWidth = coords.width;
		var first = this._imageList.getFirst("li");
		coords = first.getCoordinates();
		var width = coords.width;
		var numElements = this._imageList.getChildren("li").length;// - 1;	// number of non selected elements
		var width = (width * numElements);// + selectedWidth;
		this._imageList.setStyle("width", width + "px");
	},

	updateImage: function(url)
	{
//		this._imageElement.setProperty("src", url);
		this._imageElement.setStyle("background-image", "url(" + url + ")");
		this._imageElement.setStyle("background-repeat", "no-repeat");
		this._imageElement.setStyle("background-position", "50% 40%");
		this.fireEvent("updateImage", this);
	},


	updateTabText: function(title, text)
	{
		$("galleryTab").empty();
		if (title == "" && text == "")
		{
			$("galleryTab").setStyle("display", "none");
		}
		else
		{
			$("galleryTab").setStyle("display", "block");
			new Element("strong", {"text": title}).inject($("galleryTab"), "bottom");
			new Element("div", {"text": text}).inject($("galleryTab"), "bottom");
		}
	},

	imageClickEvent: function(e)
	{
		e.stop();
		if (typeof e.cancelBubble != "undefined")
		{
			e.cancelBubble = true;
		}
		else
		{
			e.preventDefault();
			e.stopPropagation();
		}
		var target = $(e.target);
		if (target.nodeName.toLowerCase() != "img")
		{
			target = target.getFirst("img");
		}
		// k, now we have the image, get the link
		var link = target.getParent("a");
		// and finally get the li element
		var li = link.getParent("li");
		// do we move forward or back
		if (li.getNext(".selected"))
		{
			this.back();
		}
		else if (li.getPrevious(".selected"))
		{
			this.forward();
		}
	},

	_forwardClickEvent: function(e)
	{
		e.stop();
		var target = $(e.target);
		if (!target.hasClass("disabled"))
		{
			this.forward();
		}
	},

	_backClickEvent: function(e)
	{
		e.stop();
		var target = $(e.target);
		if (!target.hasClass("disabled"))
		{
			this.back();
		}
	}

});

})();


window.addEvent("domready", function() {
	if ($("fs-filmStripContainer"))
	{
		var options = {
			container: "fs-filmStripContainer",
			imageList: "fs-filmStrip",
			forwardButton: "fs-forward",
			backButton: "fs-back",
			imageElement: "fs-mainImage",
			// the dimensions of the thumbnails in the film strip
			/*
				TODO: If the values in the dimensions are not valid (i.e. undefined, zero or null)
				then auto-configure them from the current image dimensions
			*/
			dimensions: {
				/* the dimensions of the selected thumbnail */
				selected: {
					"width": 136,		/* applied to the image */
					"height": 93,		/* applied to the image */
					"padding-top": 2	/* applied to the li element */
				},
				normal: {
					"width": 136,		/* applied to the image */
					"height": 93,		/* applied to the image */
					"padding-top": 2	/* applied to the li element */
				}
			},
			/* events if required,.all will send the FSGallery instance along with them */
			onForward: function(fsGallery) {},
			onBack: function(fsGallery) {},
			onUpdateImage: function(fsGallery) {}
		};
		new FSGallery(options);
	}
});
