/* jquery.gorillabox.js
 * lightbox plugin that will handle multiple images of multiple sizes or a div
 *  
 * Usage:	single photo, one size, thumb shows on page, larger photo in gorillabox ---- DONE ----
 *				<a href="large.jpg" rel="gorillabox"><img src="thumb.jpg" /></a>
 *				$('a[rel*="gorillabox"]').gorillabox(); (on ready) 
 *				 
 * 			single photo, multiple sizes, thumb shows on page, medium photo in gorillabox, large photo in gorillabox on click
 *				<a href="photo.jpg" class="gorillabox" rel="largephoto.jpg"><img src="photo_thumb.jpg" /></a> 
 *				$('agorillabox').gorillabox({rel: largebox});
 *				 
 *			single photo, multiple sizes, thumb shows on page, medium photo in gorillabox, magnifier shows large photo
 *				<a href="photo.jpg" class="gorillabox" rel="largephoto.jpg"><img src="photo_thumb.jpg" /></a>				 
 *				$('a.gorillabox').gorillabox({rel: magnifier});
 *				 
 *			single photo, multiple sizes, thumb shows on page, medium photo in gorillabox, large photo shown in new browser window
 *				<a href="photo.jpg" class="gorillabox" rel="largephoto.jpg"><img src="photo_thumb.jpg" /></a>				 
 *				$('a.gorillabox').gorillabox({rel: link});
 *				 
 *			multiple photos, one size each, thumbs show on page, clicked-on photo in gorillabox + thumbs of other photos
 *				<div class="images gorillabox"><a href="photo1"><img src="photo1_thumb" /></a><a href="photo2"><img src="photo2_thumb" /></a>...</div>
 *				$('div.gorillabox').gorillabox();
 *				 
 *			multiple photos, thumb shows on page, medium photo in gorillabox, large photo in gorillabox on click
 *				<div class="images gorillabox"><a href="photo1" rel="largephoto1.jpg"><img src="photo1_thumb" /></a><a href="photo2" rel="largephoto2.jpg"><img src="photo2_thumb" /></a>...</div
 *				$('div.gorillabox).multibox({rel: largebox});
 *				 
 *			multiple photos, multiple sizes with magnifier
 *				<div class="images gorillabox"><a href="photo1"><img src="photo1_thumb" rel="largephoto1.jpg" /></a><a href="photo2" rel="largephoto2.jpg"><img src="photo2_thumb" /></a>...</div 
 *				$('div.gorillabox).gorillabox({rel: magnifier});
 *				 
 *			multiple photos, multiple sizes, large photo shown in new browser window
 *				<div class="images gorillabox"><a href="photo1"><img src="photo1_thumb" rel="largephoto1.jpg" /></a><a href="photo2" rel="largephoto2.jpg"><img src="photo2_thumb" /></a>...</div 
 *				$('div.gorillabox).gorillabox({rel: link});
 *				 
 *			show a div ---- DONE ----
 *				<a href="#" rel="gorillabox>Show div</a><div id="divToShow">Some html</div>
 *				$('a[rel="gorillabox"]').gorillabox('divToShow');
 *				
 *			show an external page ---- DONE ----
 *				<a href="apage.html" rel="gorillabox">Show a page</a> 
 *				$('a[rel*=gorillabox]').gorillabox({rel:'page', width:500});   
 *				 
 *			pass html programmatically ---- DONE ----
 *				 var html = '<div>Some html</div>';
 *				 $.gorillabox(html); 
 *				  
 *			using a button: bind the mousedown event, not the click event
 * 
 * SETTINGS:	overlay settings: 		overlay: boolean (default = true) 								 ---- DONE ---- 
 *										opacity: decimal value (default = .5)							 ---- DONE ----
 *										  
 *				   										
 *				magnifier settings:		magWidth: integer (default = 200)
 *				(rel:magnifier)			magHeight: integer (default = 200)
 *																
 *				multiple images:		multiImage: boolean (default = false) 
 *				
 *				position settings:		top: integer (default = 100)									---- DONE ----
 *				
 *				size settings:			width: integer (default = 400, for html pages only) 			---- DONE ---- 
 *				
 *				callback settings:		beforeShow: function											---- DONE ----
 *										onShow: function												---- DONE ----
 *										onClose: function												---- DONE ----      
 *				
 *				
 *				rel settings:			rel: 'link' (opens link as site in new window)					---- DONE ----
 *										rel: 'largebox' (opens image link in gorillabox)  
 *										rel: 'magnifier' (creates magnifier)
 *										rel: 'page' (when showing external page)						---- DONE ----   						   
 *				        
 */

 				 
;(function($) {
$.fn.gorillabox = function(options) {

	/******************************* PRIVATE PROPERTIES **********************************/
	
	var imgobj = { // image and properties for each image
		width:		0,
		height:		0,
		thumbsrc:	'',
		medsrc:		'',
		lgsrc:		'',
		src:		''
	};
	var imgs = []; // imgobj holder		
	var info = {}; // document, window and calling object positions
	var sibs = []; // holder for non-clicked on images 
	
	var gorillaboxHtml = ''; // the html for multibox and overlay
	
	var divToShow;
	var href;	
	var rel;
	var doImage = false;
	
	/******************************* PRIVATE METHODS **********************************/
	
	// the main controller, everything starts here
	function doGorillabox() {
		// do the beforeShow callback
		try {
			options.beforeShow();
		} catch (e) {}
		
		// get info about window and document sizes
		getDocumentInfo();
		
		// get anchor attributes
		try {
			href = $(this).attr('href');
		} catch (e1) {}
		try {
			rel = $(this).attr('rel');
		} catch (e2) {
			
		}
		
		if (href) {
			// image or html of some sort?
			var ext = href.slice(-3);
			if (ext == 'jpg' || ext == 'peg' || ext == 'png' || ext == 'gif') {
				doImage = true;
			}
		}
		
		// write the html and append it to the body
		writeHtml();
		
		// append it
		$('body').append(gorillaboxHtml);	
		
		// paper or plastic?
		doImage? gorillaboxImage(href) : gorillaboxDiv();
		
		// stop default click action
		return false;
	}
		
	// write the html for the multibox using options
	function writeHtml() {
		gorillaboxHtml = '';
		// write it
		if (options.overlay) gorillaboxHtml += '<div id="gorillaboxoverlay"></div>';
		if (options.rel == 'magnifier') gorillaboxHtml += '<div id="magnifier"></div>';
		gorillaboxHtml += '<div id="gorillabox">';
		gorillaboxHtml += '<table><tbody>';
		gorillaboxHtml += '<tr><td class="tl"/><td class="bh"/><td class="tr"/></tr>';
		gorillaboxHtml += '<tr>';
		gorillaboxHtml += '<td class="bv"/>';
		gorillaboxHtml += '<td class="body">';
		gorillaboxHtml += '<div class="header">';
		gorillaboxHtml += '<a href="#" id="closeGorillabox" title="Close">Close</a>';
		if (!options.div && !options.html) gorillaboxHtml += '<span class="loading">&nbsp;</span>';
		if (options.rel == 'magnifier') gorillaboxHtml += '<a href="#" class="magnify"></a>';
		if (options.rel == 'link' && rel != '') gorillaboxHtml += '<a href="' + rel + '" class="externallink">Visit Site</a>';		
		gorillaboxHtml += '</div>';
		if (doImage === true) {
			gorillaboxHtml += '<div class="mainimage"></div>';	
		} else {
			gorillaboxHtml += '<div class="maincontent"></div>';
		}
//		if (options.multiImage && !options.div) gorillaboxHtml += '<div class="thumbs"></div>';
		gorillaboxHtml += '<div class="footer"></div>';
		gorillaboxHtml += '</td>';
		gorillaboxHtml += '<td class="bv"/>';
		gorillaboxHtml += '</tr>';
		gorillaboxHtml += '<tr><td class="bl"/><td class="bh"/><td class="br"/></tr>';
		gorillaboxHtml += '</tbody></table>';
		gorillaboxHtml += '</div>';
	}
	
	// show image(s)
	function gorillaboxImage(href) {
		imgobj.content = new Image();
		imgobj.content.src = href;
		getImageSize(loadGorillabox);
		return false;	
	}

	// load the images
	function loadGorillabox() {
		// size the .mainimage div
		$('#gorillabox .mainimage').css({
			width:		imgs[0].width,
			height:		imgs[0].height				
		});
		
		if (options.multiImage) {
			
		} else {
			$('#gorillabox .mainimage').html('<img alt="" src="' + imgs[0].content.src + '" />');
			showTheBox();
		}
		
		// size the additional images
		/* if (sibs.length > 0) {
			var addlWidth = Math.floor(imgs[0].width/(sibs.length+1)) - 13;
			//var addlWidth = Math.floor(500/(sibs.length+1)) - 13;
			$('#multibox .thumbs img').css({
				'width':	addlWidth	
			});
			// bind the change-image function to the thumbs
			changeThumb();	
		} */
		
		
	}
	
	// finally show
	function showTheBox() {
		// size the overlay
		var topPosition = info.st + options.top + 100;
		//var gorillaboxHeight = imgs[0].height + 105;
		var gorillaboxHeight, contentWidth;
		if (!options.div && options.rel != 'page' && !options.html) {
			gorillaboxHeight = imgs[0].height + 105; // + max height of thumbs
			contentWidth = $('#gorillabox .mainimage').width();
		} else {
			gorillaboxHeight = $('#gorillabox .maincontent').height() + 105;
			if (options.rel == 'page' || options.html) {
				contentWidth = options.width;
				$('#gorillabox .maincontent').css('width', contentWidth);
			} else {
				contentWidth = $('#gorillabox .maincontent').width();
			}
		}

		var overlayHeight;
		if (info.dh > (topPosition + gorillaboxHeight)) {
			overlayHeight = info.dh;	
		} else {
			overlayHeight = topPosition + gorillaboxHeight +100;
		}
		
		var overlayWidth = $('body').width();
	 	
		// animate the transparent layer if default not changed
		if (options.overlay) {
			$('#gorillaboxoverlay')
				.css({'width': overlayWidth, 'height': overlayHeight})
				.animate({opacity: options.opacity}, 400, 'linear');
		}
		
		// add the (main) image and show the multibox
		//$('#gorillabox .mainimage').html('<img alt="" src="' + imgs[0].content.src + '" />');
		$('#gorillabox')
			.css({
				top:			info.st + options.top + 100,
				'left':			'50%',				
				'margin-top':	'-100px',
				//'margin-left':	-((imgs[0].width+40)/2)
				'margin-left':	-((contentWidth + 40)/2) + info.sl
				
			})
			.animate({opacity: 1}, 400, 'linear');
			
		// bind the magnifier if needed
		if (options.magnifier) {
			bindMagnifier();
		}	
				
		// bind the close function
		removeGorillabox();
		
		// bind the full-size image popup
//			showLargeImage();

		// bind a new window to external links
		showExternalLink();
		
		// get rid of the loading gif
		$('#gorillabox span.loading').remove();
		
		// do the afterShow callback
		try {
			options.onShow();
		} catch (e) {}			
	}

	// show non-image content, this can be a hidden div on the page or an external page
	function gorillaboxDiv() {
		var contentWidth;
		if (options.rel == 'page') {
			// load the external page
			$('#gorillabox .maincontent').load(href);
		} else if (options.html) {
			// load the html
			$('#gorillabox .maincontent').html(options.html);
		} else {
			// add the div to show to the gorillabox and set it to visible (save for later)
			var divToShow = $('#'+options.div).clone(true);		
			$('#gorillabox .maincontent').append(divToShow);
			$(divToShow).css({display: 'block', 'float': 'none'});
		}
		
		// and show it
		showTheBox();
		
		// bind the close function
		removeGorillabox();
		return false;						
	}		
	
	// get all the thumbs
	function getThumbs() {
		/* // try to get the rest of the photos
		sibs = $('#maincontent a[href*=' + imgs[0].lgsrc + ']').siblings('a');
		if (sibs.length > 0) {
			// add a smaller copy of main photo, now imgs[0]
			$('#guitarbox .thumbs').append('<a href="' + imgs[0].lgsrc + '"><img class="img_current" src="'+imgs[0].medsrc+'" alt="" /></a>');				
			for (var i=0; i<sibs.length; i++) {
				// empty and refill the imgobj
				imgobj = {};
				imgobj.lgsrc = $(sibs[i]).attr('href');
				imgobj.thumbsrc = makeThumbSrc(imgobj.lgsrc);
				imgobj.medsrc = makeMediumSrc(imgobj.lgsrc);
				if (i !== sibs.length-1) {
					$('#guitarbox .thumbs').append('<a href="' + imgobj.lgsrc + '"><img src="'+imgobj.thumbsrc+'" alt="" /></a>');
				} else {
					$('#guitarbox .thumbs').append('<a href="' + imgobj.lgsrc + '"><img class="img_last" src="'+imgobj.thumbsrc+'" alt="" /></a>');
				}
				
				// preload the medium-size images in order to get their sizes when needed
				imgobj.content = new Image();
				imgobj.content.src = imgobj.medsrc;
				imgs.push(imgobj);															
			}
			loadGuitarbox();	
		} else {
			loadGuitarbox();
		}
		return false; */
	}
	
	// get the various sizes
	function getSizes() {
		
	}	
	function changeThumb() {
		$('#gorillabox .thumbs a').click(function(){
			// swap classes
			$('#gorillabox .thumbs img').removeClass('img_current');
			$(this).children('img').addClass('img_current');				
			// get the src and use it for the main image
			var href = $(this).attr('href');
			var newsrc = href.slice(0, href.lastIndexOf('.')-3) + options.mediumSuffix + href.slice(href.lastIndexOf('.'));
			$('#gorillabox .mainimage').html('<a href="' + href + '"><img src="' + newsrc + '"" alt="" /></a>');
			// hide the magnifier and wipe its background
			$('#magnifier').css({
				'display':			'none',
				'background-image':	'none'
			});
			$('#gorillabox a#magnify').removeClass('minify');
			bigimg = null;
			return false;	
		});
	}
	
	function bindMagnifier() {
		$('#gorillabox a#magnify').toggle(function(){
			// show the loading image
			$('#gorillabox span.loading').css('display', 'block');
			// switch to minify image
			$(this).addClass('minify');
			// preload the large version of the current main image
			var href = $('#gorillabox .mainimage a').attr('href');
			bigimg = new Image();
			bigimg.src = href;
			// preload the large version
			// get the size and bind the rest of the function as a callback
			getImageSize(makeMagnifier);
			return false;
		}, function(){
			// switch to magnifyimage
			$(this).removeClass('minify');
			// hide the magnifier and wipe its background
			$('#magnifier').css({
				'display':			'none',
				'background-image':	'none'
			});
		});
	}

	// create the magnifier
	function makeMagnifier() {
		// display the magnifier and put it in the general area
		$('#magnifier').css({
			'display':				'block',
			'left':					'50%',
			'top':					'50%',
			'width':				options.magWidth,
			'height':				options.magHeight,
			'margin-left':			'-100px',
			'margin-top':			'-140px',
			'background-repeat':	'no-repeat',
			'background-image':		'url(' + bigimg.src + ')',
			'background-position':	'50% 50%'
		});
		// bind the mouse events
		$('#magnifier').mousedown(function(e){
			// add the big image as a background-image
			$(this).css({'cursor': 'move'}); 	
			// get the original position of the magnifier
			var pmag = $(this).position();
			// now the mouse data
			var pmouse = e;	
			// get the position of the image for maximum move limits
			var imgpos = $('#gorillabox .mainimage').position();
			var gbpos = $('#gorillabox').position();
			var limits = {
				minX:	Math.floor(gbpos.left + imgpos.left),
				maxX:	Math.floor(gbpos.left + imgpos.left + $('#gorillabox .mainimage').width()),
				minY:	Math.floor(gbpos.top + imgpos.top),
				maxY:	Math.floor(gbpos.top + imgpos.top + $('#gorillabox .mainimage').height())
			};
			$(this).bind('mousemove', [pmag, pmouse, limits], drag);
		});
		$('#magnifier').mouseup(function(e){
			$(this).css({'cursor': 'default'});
			$(this).unbind('mousemove');
		});
	}
	
	// allow users to be able to close the lightbox
	function removeGorillabox() {
		// by clicking the overlay
		$('#gorillaboxoverlay').click(function(){
			$('#gorillaboxoverlay').animate({'opacity':'0'}, 200, 'linear', function(){
				$('#gorillabox, #gorillaboxoverlay').remove();
				$('#gorillabox #magnifier').remove();
				if (options.onClose) options.onClose();						
			});			
		});
		// by clicking the close image
		$('#closeGorillabox').bind('click', function(e){
			$('#gorillaboxoverlay').animate({'opacity':'0'}, 200, 'linear', function(e){
				$('#gorillabox, #gorillaboxoverlay').remove();
				$('#gorillabox #magnifier').remove();
				if (options.onClose) options.onClose();
			});			
			return false;
		});
		// by clicking the image itself
		$('#gorillabox .mainimage img').click(function(){
			$('#gorillaboxoverlay').animate({'opacity':'0'}, 200, 'linear', function(){
				$('#gorillabox, #gorillaboxoverlay').remove();
				$('#gorillabox #magnifier').remove();
				if (options.onClose) options.onClose();					
			});			
			return false;
		});
		// or the esc key
		$(document).keyup(function(event){
		    if (event.keyCode == 27) {
		        $('#gorillaboxoverlay').animate({'opacity':'0'}, 200, 'linear', function(){
					$('#gorillabox, #gorillaboxoverlay').remove();
					$('#gorillabox #magnifier').remove();
					if (options.onClose) options.onClose();					
				});	
		    }
		});
		
	}
	
	// opens a new window for external links
	function showExternalLink() {
		$('#gorillabox a.externallink').click(function(){
			var newwin = window.open(rel, 'Site', 'location,menubar,resizable,scrollbars,status,toolbar');
			return false;
		});
		
	}
	
	/************************************** HELPER FUNCTIONS *****************************************/
	
	// all the info about the window, document and calling element position (via scrollTop)
	function getDocumentInfo() {
		info.ww = $(window).width();
		info.wh = $(window).height();
		info.st = $(window).scrollTop();
		info.sl = $(window).scrollLeft();			
		info.dh = $(document).height();
	}
	
	// gets the image dimensions, recursive function calls passed callback on completion		
	function getImageSize(callback) {
		if (imgobj.content.complete) {
			imgobj.width = imgobj.content.width;
			imgobj.height = imgobj.content.height;
			imgs.push(imgobj);
			callback();
		} else {
			setTimeout(function(){getImageSize(callback);}, 100);
		}
	}
	
	// make the image src attributes using options.mediumSuffix and options.thumbSuffix and the large image href
	function makeMediumSrc(href) {
		return href.slice(0, href.lastIndexOf('.')-3) + options.mediumSuffix + href.slice(href.lastIndexOf('.'));	
	}
	
	function makeThumbSrc(href) {
		return href.slice(0, href.lastIndexOf('.')-3) + options.thumbSuffix + href.slice(href.lastIndexOf('.'));
	}
	
	
	
	
	// the dragging of the magnifier
	function drag(e) {
		// the magnifier original position
		var origX = e.data[0].left, origY = e.data[0].top;
		// the mouse original position
		var startX = e.data[1].clientX, startY = e.data[1].clientY;
		// the boundaries
		var minX = e.data[2].minX, maxX = e.data[2].maxX;
		var minY = e.data[2].minY, maxY = e.data[2].maxY;			
		// the change in position of the mouse
		var deltaX = startX - origX, deltaY = startY - origY;			
		// the position to go to
		var left = 	e.clientX - deltaX;
		var top = e.clientY - deltaY;			
		// the width of the visible image
		var sWidth = e.data[2].maxX - e.data[2].minX;
		var sHeight = e.data[2].maxY - e.data[2].minY;
		//var ratio = dimensions.width/sWidth;
		//var ratio = dimensions.width/300;
		var bl = ((left-sWidth-100) / sWidth) * 100;
		var bt = ((top-minY-100) / sHeight) * 100;
		$(this).css({
			'left':					left + 'px',
			'top':					top + 'px',				
			'background-position':	bl + '% ' + bt + '%'
		});				
	}
		
	// the clone function
	/* function clone(object) {
		function F() {};
		F.prototype = object;
		return new F;
	} */	
	
	/************************************** PUBLIC *****************************************/
	
	return this.each(function(){
		
		var defaults = {
			// overlay settings
			overlay:		true,
			opacity:		.5,
			
			// for a div
			div:			null,
			
			// for html
			html:			null,
			
			// multiple size images (thumb, medium, large)
			multiSize:		false,
			thumbSuffix:	'_thumb',
			mediumSuffix:	'_med',
			
			// magnifier settings for multiple size images
			//magnifier:		false,
			magWidth:		200,
			magHeight:		200,
			
			// multiple images
			multiImage:		false,
			
			// position settings
			top:			100,
			
			// size settings
			width:			400,
			
			// callbacks
			beforeShow:		null,
			onShow:		null,
			onClose:		null
		};
		
		function extend(options) {
			for (var name in options) {
				//console.log('name: '+name+', old: '+defaults[name]+', new: '+options[name]);
				defaults[name] = options[name];
			}
			return defaults;
		}

//console.log('defaults.multiSize: '+defaults.multiSize)
			options = options ? extend(options) : defaults;
//console.log('options.multiSize: '+options.multiSize)		
		
			
			$(this).bind('click', options, doGorillabox);
	
	
		
	});
	
				
}; // end plugin
})(jQuery);

