/**
 * jAlbums - Managing jCarousel with a JSON source
 *
 * Copyright (c) 2007 Christian Fecteau
 *
 * Built on top of the jCarousel library
 *   http://sorgalla.com/jcarousel/
 */

function jAlbums($params) {
	this.$ = $params;

	// required!!!
	this.$.albums = $params.albums; // JSON albums
	this.$.containerId = $params.containerId; // where to append albums
	this.$.instanceName = $params.instanceName; // for out of scope calls like in getNavAlbum

	// defaulted, used sometimes
	this.$.getItemHTML = $params.getItemHTML || this.getItemHTML;
	this.$.imageHeight = $params.imageHeight || 75;
	this.$.imageWidth = $params.imageWidth || 75;
	this.$.jcarouselWrap = $params.jcarouselWrap || null;
	this.$.keepInCache = new Array($params.keepInCache || 20);
	this.$.noNav = $params.noNav || false;
	this.$.useThickbox = $params.useThickbox || false;
	this.$.visibleLoad = $params.visibleLoad || 3;
	this.$.itemMarginRight = $params.itemMarginRight || 10;

	// could be changed later
	this.$.albumClassName = 'album-container';
	this.$.navId = $params.instanceName;

	this.addCSSRules();
}

jAlbums.prototype = {
	addCSSRules: function() {
		var sheets = document.styleSheets;
		if (!sheets)
			return;
		var sheet;
		for (var i = 0; i < sheets.length; ++i) {
			if (!sheets[i].href)
				continue;
			if (new RegExp("jcarousel\.css").test(sheets[i].href)) {
				sheet = sheets[i];
				break;
			}
		}
		var position = "unknown DOM model";
		try{ position = sheet.rules.length }catch(e){}
		try{ position = sheet.cssRules.length }catch(e){}
		if (position == "unknown DOM model")
			return;
		function insertRule(sheet, position, selector, declaration) {
			if (sheet.insertRule) // W3C DOM http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSStyleSheet-insertRule
				sheet.insertRule(selector + " { " + declaration + " }", position);
			else if (sheet.addRule) // IE7 DOM http://msdn2.microsoft.com/en-us/library/aa358796.aspx
				sheet.addRule(selector, declaration, position);
		}
		var width =
			this.$.imageWidth * this.$.visibleLoad +
			(this.$.visibleLoad - 1) * this.$.itemMarginRight;
		var selectors = {
			jcarouselContainer: "div.jcarousel-container.jcarousel-container-horizontal",
			jcarouselClipHorizontal: "div.jcarousel-container div.jcarousel-clip-horizontal",
			jcarouselItem: "div.jcarousel-container div.jcarousel-clip-horizontal ul.jcarousel-list li.jcarousel-item",
			jcarouselItemHorizontal: "div.jcarousel-container div.jcarousel-clip-horizontal ul.jcarousel-list li.jcarousel-item-horizontal",
			jcarouselItemPlaceholder: ".jcarousel-item-placeholder"
		};
		var css = [
			{selector: selectors.jcarouselContainer,
				declaration: "width:" + width + "px"},
			{selector: selectors.jcarouselClipHorizontal,
				declaration: "width:" + width + "px"},
			{selector: selectors.jcarouselClipHorizontal,
				declaration: "height:" + this.$.imageHeight + "px"},
			{selector: selectors.jcarouselItem,
				declaration: "width:" + this.$.imageWidth + "px"},
			{selector: selectors.jcarouselItem,
				declaration: "height:" + this.$.imageHeight + "px"},
			{selector: selectors.jcarouselItemPlaceholder,
				declaration: 'background-image:url("loading-small.gif")!important'},
			{selector: selectors.jcarouselItemPlaceholder,
				declaration: "background-position:center center!important"},
			{selector: selectors.jcarouselItemPlaceholder,
				declaration: "background-repeat:no-repeat!important"},
			{selector: selectors.jcarouselItemHorizontal,
				declaration: "margin-right:" + this.$.itemMarginRight + "px" }
		].reverse();
		for (var i = 0; i < css.length; i++)
			insertRule(sheet, position, css[i].selector, css[i].declaration);
	},
	adjustAlbum: function(album, itemsToLoad) {
		var ul = document.getElementById(album.name);
		var albumSelector = '.' + this.$.albumClassName;
		var albumDom = $(ul).parents(albumSelector);
		// hide arrows
		if (itemsToLoad < this.$.visibleLoad || itemsToLoad == album.images.length)
			$('.jcarousel-next, .jcarousel-prev').css("display","none");
		// fixIE6 PNG
		if (document.fireEvent && !window.XMLHttpRequest) {
			$('.jcarousel-next')[0].addBehavior("lib/iepngfix/iepngfix.htc");
			$('.jcarousel-prev')[0].addBehavior("lib/iepngfix/iepngfix.htc");
		}
		// appear effect
		$(albumDom).hide().slideDown(); // get parentNode with @albumClassName for effect
	},
	getItemHTML: function(i, album, _this) {
		var image = album.images[i];
		var isNavAlbum = (album.name == _this.$.navId);
		var className = _this.$.useThickbox && !isNavAlbum ? 'thickbox' : false;
		var height = ' height="' + _this.$.imageHeight + '" ';
		var title = image.title || false;
		var width = ' width="' + _this.$.imageWidth + '" ';
		className = className ? ' class="' + className + '" ' : '';
		title = title ? ' title="' + title + '" ' : '';
		var out = '<a ' + title + className +
			' href="' + (image.href || image.thumb) +
			'"><img border="0" ' +
			width + height +
			' src="' + (image.thumb || image.href) +
			'" /></a>';
		out = out.replace(/  /g,' ');
		return out;
	},
	getNavAlbum: function() {
		var album = {
			"name": this.$.navId,
			"images": []
		};
		for (var i = 0; i < this.$.albums.length; ++i) {
			var _this = this.$.instanceName;
			var albumName = this.$.albums[i].name;
			var href = 'javascript:' +
				_this + ".navCallBack(" + _this + '.$.albums[' + i + '])';
			var firstImage = this.$.albums[i].images[0].thumb;
			album.images.push({
				"name": albumName,
				"thumb": firstImage,
				"href": href
			});
		}
		return album;
	},
	getPreloadImagesData: function(album) {
		var arr = $.makeArray($('#'+album.name+' li'));
		var len = arr.length;
		var first = $(arr[0]).attr('jcarouselindex');
		var last = $(arr[len-1]).attr('jcarouselindex');
		return [first, last, album.images];
	},
	jcarousel_itemLoadCallback: function(carousel, state) {
		var album = carousel.options.album;
		var _this = carousel.options.jAlbums;
		if (carousel.prevFirst != null)
			for (var i = carousel.prevFirst; i <= carousel.prevLast; i++)
				carousel.remove(i);
		var per_page = carousel.last - carousel.first + 1;
		var currPage = 0;
		var first,last;
		var isNavAlbum = (album.name == _this.$.navId);
		for (var i = carousel.first; i <= carousel.last; i++) {
			var page = Math.ceil(i / per_page);
			if (currPage != page) {
				currPage = page;
				first = ((page - 1) * per_page) + 1;
				last = first + per_page - 1;
				first = first < carousel.first ? carousel.first : first;
				last = last > carousel.last ? carousel.last : last;
				if (carousel.has(first, last))
					continue;
				for (var j = first; j <= last; j++)
					carousel.add(j, _this.$.getItemHTML(j-1, album, _this));
			}
		}
		_this.preloadImages(carousel.first, carousel.last, album.images);
		if (_this.$.useThickbox)
			_this._jcarousel_manageThickBox(carousel, state, _this);
		if (isNavAlbum)
			_this.navSelected(_this, album);
	},
	_jcarousel_manageThickBox: function(carousel, state, _this) {
		if (state == 'init' || !_this.isPutting) { /* fix IE7: itemLoadCallback is called twice for nothing */
			for (var i = carousel.first; i <= carousel.last; i++) {
				var domChunk = $('a.thickbox', carousel.get(i));
				domChunk.unbind('click',tb_show_click); // thickbox se fait deux fois si les items ne sont pas détruits et recréés comme à la fin d'un album dont le nombre de photos n'est pas divisible par 6 alors on unbind le click qui fire deux fois sinon et ça règle le bogue
				tb_init(domChunk);
			}
			carousel.funcResize = function(){}; /* bogue jcarousel with thickbox */
		}
	},
	navCallBack: function(albumToAdd) {
		this.undoPutAlbum();
		this.putAlbum(albumToAdd);
	},
	navSelected: function(_this, album) {
		$('#'+_this.$.navId+' li a').unbind("click").click(function(eventObject) {
			var li = this.parentNode;
			var ul = li.parentNode;
			var lis = $(ul.getElementsByTagName('li'));
			$(lis).each(function(index, domElement) {
				$(domElement).fadeTo("fast", 1);
			});
			$(li).fadeTo("slow", 0.33);
			$(ul).attr("jalbumsselected", $(li).attr('jcarouselindex'));
		});
		$('#'+_this.$.navId+' li').each(function(index, domElement) {
			var selected = $(domElement.parentNode).attr("jalbumsselected");
			var jcarouselindex = $(domElement).attr('jcarouselindex');
			if (selected == jcarouselindex)
				$(domElement).fadeTo("slow", 0.33);
		});
	},
	preloadImages: function(first, last, $images) {
		first = parseInt(first); // doesn't cast automatically to integer, didn't mind to find why
		last = parseInt(last); // doesn't cast automatically to integer, didn't mind to find why
		var firstPrev = first - 2; // jcarousel array begins with 1
		for (var i = 0, length = parseInt(this.$.keepInCache.length / 2); i < length; ++i) {
			var next = $images[i + last] ?
				($images[i + last].thumb || $images[i + last].href) : false;
			if (next)
				this.putInCache(next);
			var prev = $images[firstPrev - i] ?
				($images[firstPrev - i].thumb || $images[firstPrev - i].href) : false;
			if (prev)
				this.putInCache(prev);
		}
	},
	putAlbum: function(album) {
		this.isPutting = true;
		var itemsToLoad = Math.min(this.$.visibleLoad, album.images.length);
		var albumHTML = "";
		var fixIE7 = window.ActiveXObject ? ' style="min-height:1px" ' : '';
		albumHTML += '<div ' + fixIE7 + ' class="'+this.$.albumClassName+'">';
			albumHTML += '<ul id="' + album.name + '" class="jcarousel-skin-tango">';
			for (var i = 0; i < itemsToLoad; ++i)
				albumHTML += ('<li>' + this.$.getItemHTML(i, album, this) + '</li>');
			albumHTML += '</ul>';
		albumHTML += '</div>';
		$('#'+this.$.containerId).append(albumHTML);
		var ul = document.getElementById(album.name);
		$(ul).jcarousel({
			jAlbums: this,
			album: album,
			itemsToLoad: itemsToLoad,
			vertical: false,
			start: 1,
			size: album.images.length,
			scroll: itemsToLoad,
			visible: itemsToLoad,
			animation: "fast",
			easing: null,
			auto: 0,
			wrap: this.$.jcarouselWrap,
			initCallback: this.jcarousel_initCallback,
			itemLoadCallback: this.jcarousel_itemLoadCallback,
			buttonNextHTML: '<div></div>',
			buttonPrevHTML: '<div></div>',
			buttonNextEvent: "click",
			buttonPrevEvent: "click"
		});
		this.adjustAlbum(album, itemsToLoad);
		this.isPutting = false;
	},
	putInCache: function(src) {
		var img = new Image();
		img.src = src;
		var removeImg = this.$.keepInCache.shift();
		if (removeImg)
			delete removeImg;
		this.$.keepInCache.push(img);
	},
	undoPutAlbum: function() {
		// get nodes with @albumClassName for removal
		var albumsSoFar = $('#'+this.$.containerId+' .'+this.$.albumClassName);
		var lastAlbum = albumsSoFar[albumsSoFar.length-1];
		if (!this.$.noNav && albumsSoFar.length == 1)
			return;
		lastAlbum.parentNode.removeChild(lastAlbum);
	}
}

// modif to thickbox.js so I can unbind the click and set path to loading image
	function tb_show_click() {
		var t = this.title || this.name || null;
		var a = this.href || this.alt;
		var g = this.rel || false;
		tb_show(t,a,g);
		this.blur();
		return false;
	}
	function tb_init(domChunk) {
		$(domChunk).click(tb_show_click);
	}
	tb_pathToImage =
		$("script[src$='thickbox.js']")[0].src.replace(/thickbox\.js$/,'') +
		"loadingAnimation.gif";
	$(document).ready(function() {
		imgLoader = new Image();// preload image
		imgLoader.src = tb_pathToImage;
	});

/**
 * 	jAlbums
 *
 * 	required:
 * 	- containerId
 * 	- instanceName
 * 	- albums
 *
 *
 * 	Library built over http://sorgalla.com/jcarousel/ that requires a
 * 	JSON reference object to manage jcarousel in a page context like this:
 *
 * 	The carousels are appended to a single DOM container and the first carousel is
 * 	navAlbum if option's used. The click action for thumbs can be customized through
 * 	the name key for the image with the href javascript pseudo protocol
 *
 * 	No styling is done here. see jcarousel's css for tango skin to overwrite its style
 * 	The methods provided by jAlbums could hopefully be implanted in other contexts and are:
 *
 * 	- putNav() returns the JSON for an album of all albums
 * 	- jcarousel_itemLoadCallback() when next/previous are clicked
 * 	- putAlbum() receives a JSON album, returns nothing
 * 	- getItemHTML() as a user-defined helper to customize inner HTML of LIs created
 *
 *
 * 	minimal code to init:
 * 	---------------------
 * 	var albums;
 * 	var myjAlbums;
 * 	$(document).ready(function() {
 * 		albums = getAlbums();
 * 		myjAlbums = new jAlbums({
 * 			"containerId": containerId, // albums container (only one right now)
 * 			"instanceName": "myjAlbums",  // for back reference: jAlbums.instanceName
 * 			"albums": albums // a JSON object representing albums
 * 		});
 * 	});
 *
 *
 * 	minimal JSON albums structure is this array of hashes with these required properties:
 * 	-------------------------------------------------------------------------------------
 * 	function getAlbums() {
 * 		return [
 * 			{
 * 				"name": "myalbum01", // id
 * 				"images":
 * 				[
 * 					{
 * 						"href": "/mytfulls/myalbum01image01.jpg", // could be javascript:mycode
 * 						"name": "myalbum01image01", // id
 * 					},
 * 					{
 * 						"href": "/mytfulls/myalbum01image01.jpg",
 * 						"name": "album01image02", // id
 * 					}
 * 				]
 * 			}
 * 		];
 * 	}
 *
 *
 * 	minimal item HTML is :
 * 	----------------------
 * 	<a href="href"><img src="thumb" /></a>
 *
 * 	params:
 */
