/**
 * Script to handle fading galleries on the site
 */

/**
 * Gallery manager
 */
var GalleryManager = {
	/* Contains the defined galleries */
	list : [],
	/**
	 * Returns a random millisecond interval
	 */
	getGalleryInterval : function () {
		/* Return a pseudo-random number in the thousands -- ensure at least 6 seconds */
		var pseudo = Math.round(Math.random() * 6000);
			pseudo += 6000;
		return pseudo;
	},
	/**
	 * Sets up the galleries on any page
	 */
	setup : function () {
		/* Search for any galleries */
		var galleries = $('div.gallery');
		GalleryManager.list = new Array();
		
		/* Loop through the found objects */
		$.each(galleries, function (idx, elem) {
			/* Create the object */
			var gal = new Gallery($(elem));
				gal.intervalNumber = GalleryManager.getGalleryInterval();
			GalleryManager.list.push(gal);
		});
	},
	/**
	 * Resumes animation of the galleries
	 */
	start : function () {
		/* Loop through the list of registered galleries and call start */
		var idx,
			idx_elem;
		for (idx = 0; idx <= GalleryManager.list.length; idx++) {
			idx_elem = GalleryManager.list[idx];
			idx_elem.doStart();
		}
	},
	/**
	 * Stops the animation of galleries
	 */
	stop : function () {
		/* Loop through galleries to call stop */
		var idx,
			idx_elem;
		for (idx = 0; idx <= GalleryManager.list.length; idx++) {
			idx_elem = GalleryManager.list[idx];
			idx_elem.doStop();
		}
	}
}


/* Wait for page load on the gallery manager */
$(function () {
	GalleryManager.setup();
});


/**
 * Gallery object
 * @param Object The DOM to use for the gallery
 */
function Gallery (dom) {
	/* Save the dom */
	this.dom = dom;
	this.list = new Array();
	this.load = new Array();
	this.interval = null;
	this.intervalNumber = 0;
	this.currentIndex = -1;
	
	/* Determine the gallery type */
	this.type = 'sequential';
	if (this.dom.hasClass('gallery-random')) {
		this.type = 'random';
	}
	
	/* Find all the images */
	var _this = this,
		images = this.dom.find('img');
	$.each(images, function (idx, elem) {
		/* Save the image into the list */
		_this.load.push($(elem).attr('src'));
	});
	
	/* Remove the images so we load them sequentially */
	this.dom.find('img').remove();
	
	/* Start the load process */
	this.doLoad();
}
/**
 * The image being currently shown
 */
Gallery.prototype.currentImageIndex = null;
/**
 * Starts the loading process
 */
Gallery.prototype.doLoad = function () {
	/* See if we have any images left */
	if (this.load.length <= 0) {
		this.doStart();
		return;
	}
	
	/* Take out the next image */
	var _this = this,
		next = this.load.shift(),
		img = new Image();
		img.onload = function (event) {
			_this.onImageLoad(event);
		};
	
	/* Add the image to the array */
	this.list.push(img);
	img.src = next;
}
/**
 * Starts the loading process
 */
Gallery.prototype.doStart = function () {
	/* See if there are more than one image */
	if (this.list.length == 0) {
		return;
	}
	if (this.list.length == 1) {
		this.onIntervalSequential();
		return;
	}
	
	/* Start the interval */
	var _this = this;
	switch (this.type) {
		case 'random':
			this.onIntervalRandom();
			this.interval = setInterval(function () {
				_this.onIntervalRandom();
			}, this.intervalNumber);
			break;
		case 'sequential':
			this.onIntervalSequential();
			this.interval = setInterval(function () {
				_this.onIntervalSequential();
			}, this.intervalNumber);
			break;
	}
}
/**
 * Stops the slideshow
 */
Gallery.prototype.doStop = function () {
	/* Kill the interval */
	if (this.interval) {
		clearInterval(this.interval);
	}
}
/**
 * Runs on image loading
 */
Gallery.prototype.onImageLoad = function (event) {
	/* Add the image to the dom */
	var img_tag = this.list[this.list.length - 1],
		img = $(img_tag);
	img_tag.zIndex = this.load.length;
	this.dom.append(img);
	
	/* Prepare the image */
	img.css({
		'opacity' : 0,
		'display' : 'block'
	});
	
	/* Call up the loader again */
	this.doLoad();
}
/**
 * Runs when an interval elapses for the random type
 */
Gallery.prototype.onIntervalRandom = function () {
	/* See if the index is set */
	var img;
	if (this.currentIndex >= 0) {
		img = $(this.list[this.currentIndex]);
		img.animate({
			'opacity' : 0
		}, 2000);
	}
	
	/* Find a random index */
	var indx = 0,
		keep_looking = true;
	while (keep_looking) {
		indx = Math.round(Math.random() * (this.list.length - 1));
		if (indx != this.currentIndex) {
			keep_looking = false;
			this.currentIndex = indx;
			break;
		}
	}
	
	/* Fade in the new item */
	img = $(this.list[this.currentIndex]);
	img.animate({
		'opacity' : 1
	}, 2000);
}
/**
 * Runs when an interval elapses for the sequential type
 */
Gallery.prototype.onIntervalSequential = function () {
	/* Run to the next image */
	var img;
	if (this.currentIndex >= 0) {
		img = $(this.list[this.currentIndex]);
		img.animate({
			'opacity' : 0
		}, 2000);
	}
	
	/* Go to the next iteration */
	var indx = ((this.currentIndex + 1) >= this.list.length) ? this.currentIndex + 1 : 0;
	img = $(this.list[indx]);
	img.animate({
		'opacity' : 1
	}, 2000);
	this.currentIndex = indx;
}


/**
 * Controls creating the clickable galleries
 */
var ClickableGalleryManager = {
	/* The list of items in the gallery */
	list : [],
	/**
	 * Polls the dom for gallery candidates
	 */
	setup : function () {
		/* Get the galleries that need to be set up */
		ClickableGalleryManager.list = new Array();
		var galleries = $('.media-setup');
		$.each(galleries, function (idx, elem) {
			ClickableGalleryManager.list.push(new ClickableGallery(elem));
		});
	}
}
/**
 * Represents one clickable gallery
 * @param jQuery The object containing the images
 */
function ClickableGallery (obj) {
	/* The selected index */
	this.dom = $(obj);
	this.selected = -1;
	this.length = 0;
	this.setup();
}
/**
 * Selects the passed index
 * @param Integer The index to select
 */
ClickableGallery.prototype.doSelect = function (idx) {
	/* Deselect the old one */
	if (this.selected > -1) {
		var old_item = this.dom.children(':eq('+this.selected+')')
			.stop(true, false)
			.animate({
				'opacity' : 0
			}, 500, function () {
				old_item.css('display', 'none');
			});
	}
	
	/* Change the index and animate it in */
	this.selected = idx;
	this.dom.children(':eq('+this.selected+')')
		.stop(true, false)
		.css('display', 'block')
		.animate({
			'opacity' : 1
		}, 500);
	
	/* Call the method to update the info span */
	this.updateStatus();
}
/**
 * Runs when the next button is clicked
 * @param Object The event
 */
ClickableGallery.prototype.onNextClick = function (event) {
	/* See if we need to mod the index to wrap */
	var idx = this.selected + 1;
	if (idx >= this.length) {
		idx = 0;
	}
	this.doSelect(idx);
}
/**
 * Runs when the prev button is clicked
 * @param Object The event data
 */
ClickableGallery.prototype.onPrevClick = function (event) {
	/* See if we need to change the id */
	var idx = this.selected - 1;
	if (idx < 0) {
		idx = this.length - 1;
	}
	this.doSelect(idx);
}
/**
 * Function to set up the gallery
 */
ClickableGallery.prototype.setup = function () {
	/* Remove the setup class and replace with the gallery class */
	this.dom.removeClass('media-setup').addClass('media');
	
	/* Remove visibility of the images */
	this.elems = this.dom.children();
	this.length = this.elems.size();
	if (this.length <= 1) {
		/* No need to set up controls */
		return;
	}
	this.dom.children().css({
		'opacity' : 0,
		'display' : 'none'
	});
	
	/* Create the controls */
	var _this = this;
	var controls = $('<a href="#prev" class="gal-prev"><img src="/design/gallery-prev.png" alt="<" /></a><span class="gal-info"></span><a href="#next" class="gal-next"><img src="/design/gallery-next.png" alt=">" /></a>');
	this.dom.parent().find('.controls').html(controls);
	this.dom.parent().find('.gal-prev').click(function (event) {
		_this.onPrevClick(event);
	});
	this.dom.parent().find('.gal-next').click(function (event) {
		_this.onNextClick(event);
	});
	
	/* Select the first image */
	this.doSelect(0);
}
/**
 * Causes an update to the status text
 */
ClickableGallery.prototype.updateStatus = function () {
	/* Set the text */
	var txt = (this.selected + 1) + ' of ' + this.length;
	this.dom.parent().find('.gal-info').text(txt);
}
/**
 * Add a listener to create clickable galleries
 */
$(function () {
	ClickableGalleryManager.setup();
});

