/**
 * AstonishMe Simple Gallery plugin for jQuery
 *
 * @package AstonishMe SimpleGallery
 *
 * @copyright (c)2008 by AstonishMe - {@link http://astonishme.co.uk/}.
 *
 * {@internal Below is a list of authors who have contributed to design/coding of this file: }}
 * @author Yabba	- {@link http://www.astonishme.co.uk/}
 * @author Stk		- {@link http://www.astonishme.co.uk/}
 *
 * @license GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
 *
 */

if( !jQuery().data( 'amsgGalleryPluginLoaded' ) )
{ // avoid duplicating ourselves
	jQuery().data( 'amsgGalleryPluginLoaded', true );
	jQuery( '<!--[if IE]><style type="text/css">#amsgWindow{ filter:alpha( opacity=85); /* stk mod */ } #amsgWindow #amsgSimpleName{ filter:alpha( opacity=40); }</style><script type="text/javascript">var amsgIsIE = true;</script><![endif]-->' ).appendTo( 'head' );
	jQuery.fn.extend({

		/**
		 * Gallerys all images within the selector
		 *
		 * @param mixed settings :
		 *  string url : replaces the url in gallery image links - preserves query string
		 *	string key : apended to url in gallery image links
		 *	array trans : translation array. A list of the current strings can be found in
		 *		/locales/_default.lang.js
		 */
		amSimpleGallery: function( settings )
		{
			// store settings
			jQuery().data( 'amsgSettings', jQuery.extend( jQuery.extend({
				url: '', // used to overide link urls
				queryString: '', // additional query string params
				share: false, // displays a "share this" link
//				forum: false, // regex replacement for forum links or false for none
				duplicates: 'move', // action to take with duplicates : move, ignore
				minWidth: 0, // minimum width in pixels for an image to be added
				minHeight: 0, // minimum height in pixels for an image to be added
				detailTitle: 'alt', // should image alt or title be used for detailed image title
				detailCaption: 'title', // should image alt or title be used for detailed image caption
				trans: Array() // translation strings
			}, jQuery().data( 'amsgSettings' ) ), settings ) );

			if( !jQuery( 'div' ).is( '#amsgWindow' ) )
			{ // need to add our overlay stuff
				jQuery( '<div id="amsgWindow" onclick="jQuery().amsgCloseScreen();" title=" '+jQuery().amsgTranslate('Click the screen to close the gallery')+' ">&nbsp;</div>' ).appendTo( 'body' );
				jQuery( '<p id="amsgSimpleName"><!--ugly logo--></p>' ).appendTo( '#amsgWindow' );
				jQuery( '<div id="amsgScreen" onclick="jQuery().amsgCloseScreen();" title=" '+jQuery().amsgTranslate('Click the screen to close the gallery')+' ">&nbsp;</div>').appendTo( 'body' );
				jQuery( '<div id="amsgPreload">&nbsp;</div>').appendTo( 'body' );
				jQuery( window ).resize( function(){ jQuery().amsgResize(); });
			}

			jQuery(this).each( function(){	// loop through each gallery
				var amsgGallery = jQuery( this ); // set gallery
				var amsgImages = new Array(); // set images
				jQuery( this ).find( 'a > img' ).each( function(){ // loop through all images
					if( jQuery( this ).width() > jQuery().data( 'amsgSettings' ).minWidth // is it wide enough
					&& jQuery( this ).height() > jQuery().data( 'amsgSettings' ).minHeight // is it high enough
					&& (
					jQuery().data( 'amsgSettings' )['duplicates'] != 'ignore' // default is to move
					|| !jQuery( this ).data( 'amsgGallery' ) // is it in a gallery already
					)
					)
					{	// we want to add this image
						if( jQuery( this ).data( 'amsgGallery' ) )
						{ // already in a gallery, remove it
							var amsgTempImages = new Array();
							var amsgTempGallery = jQuery( this ).data( 'amsgGallery' ).data( 'amsgImages' );
							for( amsgTempImage in amsgTempGallery )
							{ // loop through current gallery images
								if( amsgTempGallery[ amsgTempImage ].attr( 'src' ) != jQuery( this ).attr( 'src' ) )
								{ // this one's to stay here
									amsgTempImages[ amsgTempImages.length ] = amsgTempGallery[ amsgTempImage ];
								}
								// store new gallery details
								jQuery( this ).data( 'amsgGallery' ).data( 'amsgImages', amsgTempImages );
							}
						}
						jQuery( this ).data( 'amsgGallery', amsgGallery ); // set gallery

						var amsgSource = jQuery( this ).parent().attr( 'href' ); // get full size image url

						if( amsgNewUrl = jQuery().data( 'amsgSettings' ).url )
						{	// we want to pull the image from a different location
							amsgSource = amsgSource.replace( /^.+?(\?.+?)?(#.+?)?$/, amsgNewUrl + '$1' );// strip url to just query string
						}

						var amsgGlue = ( amsgSource.indexOf( '?' ) ? '&' : '?' );
						if( amsgQueryString = jQuery().data( 'amsgSettings' ).queryString )
						{ // we need to append this to the query string
							amsgSource += amsgGlue + amsgQueryString;
						}
						jQuery( this ).data( 'amsgDetail', amsgSource ); // set source


						jQuery( this ).unbind( 'click' ); // cancel any previous onclicks
						jQuery( this ).click( function(e){ // add the onclick stuff
							if( typeof( amsgIsIE ) != 'undefined' && !jQuery('html').hasClass('amsgWindowOpen' ) )
							{	// IE6 crap
								amsgParent = jQuery(this).data('amsgGallery').offset();
								jQuery('body').data('amsgLeft', amsgParent.left );
								jQuery('body').data('amsgTop', amsgParent.top );
//								window.alert( jQuery('body').data('amsgTop') );
								window.scrollTo( 0,0 );
							}
							jQuery( 'html' ).addClass( 'amsgWindowOpen' ); // open the screen
							jQuery().amsgLoadImage( jQuery( this ) ); // load the image
							return false; // kill the click
						});
						amsgImages[ amsgImages.length ] = jQuery( this ); // add the image
					}
				});
				jQuery( this ).data( 'amsgImages', amsgImages ); // add gallerys images
				jQuery( this ).data( 'amsgSettings', jQuery().data( 'amsgSettings' ) );
			});
		},


		/**
		 * Preloads the cureent, previous and next images
		 * Automatically displays the current image when loaded
		 *
		 & @param img image : the image to load
		 */
		amsgLoadImage : function( image )
		{
			// reset pointers
			var amsgPrevious = '';
			var amsgNext = '';
			var amsgFound = false;

			// loop through images in gallery
			var amsgGallery = jQuery( image ).data( 'amsgGallery' ).data( 'amsgImages' );
			for( amsgImage in amsgGallery )
			{
				//window.alert( jQuery( amsgGallery[ amsgImage ] ).data( 'amsgDetail' ) );
				if( amsgFound && !amsgNext )
				{ // this is the next image
					amsgNext = amsgImage;
				}

				if( image.attr( 'src' ) == amsgGallery[amsgImage].attr( 'src' ) )
				{ // this is the current image
					amsgFound = true;
				}

				if( !amsgFound )
				{ // this will eventually point to the previous image
					amsgPrevious = amsgImage;
				}
			}

			if( !amsgPrevious )
			{ // we are on the first image
				amsgPrevious = amsgGallery.length - 1;
			}

			if( !amsgNext )
			{ // we are on the last image
				amsgNext = 0;
			}
			jQuery( image ).data( 'amsgPrevious', amsgPrevious );
			jQuery( image ).data( 'amsgNext', amsgNext );
			if( jQuery( image ).data( 'amsgLoaded' ) )
			{ // image already loaded
				jQuery().amsgDisplayImage( image ); // display image, alt, title, previous, next, (optional) share this
			}
			else
			{ // need to pre-load the image
				jQuery().amsgPreloadImage( image, true );// need to get this one to trigger off "loaded"
			}
			// preload images either side of current image
			jQuery().amsgPreloadImage( jQuery( amsgGallery[ amsgPrevious ] ), false ); // preload next image
			jQuery().amsgPreloadImage( jQuery( amsgGallery[ amsgNext ] ), false ); // preload previous image
			return false;
		},


		/**
		 * Preloads an image
		 *
		 * @param object amsgImage : Image to preload
		 * @param boolean amsgDisplay : should we auto-display once loaded
		 *
		 * @ return object amsgPreload : the preloaded object
		 */
		amsgPreloadImage: function( amsgImage, amsgDisplay )
		{
			if( !jQuery( amsgImage ).data( 'amsgLoaded' ) )
			{ // not preloaded
				var amsgPreload = jQuery( '<img src="'+jQuery( amsgImage ).data( 'amsgDetail' )+'" />' );
				jQuery( amsgPreload ).data( 'amsgParent', jQuery( amsgImage ) );
				jQuery( amsgPreload ).data( 'amsgDisplay', amsgDisplay );
				jQuery( amsgPreload ).bind( 'load', function(){	// onload function
					var amsgParent = jQuery( this ).data( 'amsgParent' ); // set parent image
					jQuery( amsgParent ).data( 'amsgLoaded', true ); // set preloaded flag
					jQuery( amsgParent ).data( 'amsgWidth', jQuery( this ).width() ); // store original height
					jQuery( amsgParent ).data( 'amsgHeight', jQuery( this ).height() ); // store original width
					if( jQuery( this ).data( 'amsgDisplay' ) )
					{ // we want to display the image
						jQuery().amsgDisplayImage( jQuery( amsgParent ) );
					}
				});
				jQuery( amsgPreload ).bind( 'error', function(){ // on error function
					var amsgParent = jQuery( this ).data( 'amsgParent' );
					window.alert( jQuery().amsgTranslate( 'Failed to load' ) + ' : ' + jQuery( amsgParent ).parent().attr( 'href' ) ); // inform user
					jQuery( '#amsgScreen' ).empty();
					jQuery().amsgCloseScreen(); // close the overlay
				});
				jQuery( amsgPreload ).appendTo( '#amsgPreload' );
				return amsgPreload;
			}
			if( amsgDisplay )
			{ // we want to display the image
				jQuery().amsgDisplayImage( amsgImage );
			}
		},


		/**
		 * Translates strings into locale
		 *
		 * @param string string : the string to translate
		 *
		 * @return string string : the translated string if available, or the original string if not
		 */
		amsgTranslate: function( string )
		{
			var translations = jQuery().data( 'amsgSettings' ).trans;
			if( typeof( translations[ string ] ) != 'undefined' && translations[ string ] )
			{	// use translated string
				string = translations[ string ];
			}
			return string; // return translated string
		},


		/**
		 * Displays an image ... original huh?
		 *
		 * @param object image : the image top display
		 */
		amsgDisplayImage: function( image )
		{
			jQuery( '#amsgScreen' ).animate({opacity:.6},100, 'swing',function(){
				jQuery( '#amsgScreen' ).empty();
				// build image details
				var amsgGallery = jQuery( image ).data( 'amsgGallery' ).data( 'amsgImages' );
				var amsgSettings = jQuery( image ).data( 'amsgGallery' ).data( 'amsgSettings' );
				if( amsgGallery[ image.data( 'amsgPrevious' ) ].attr( 'src' ) != image.attr( 'src' ) )
				{
					// build "previous" thumb
					var amsgPrevious = jQuery( '<img class="amsgPrevious" style="width:80px;" src="'+amsgGallery[ image.data( 'amsgPrevious' ) ].attr( 'src' )+'" title=" '+jQuery().amsgTranslate('View the previous image')+' " />' );
					jQuery( amsgPrevious ).data( 'amsgParent', amsgGallery[ image.data( 'amsgPrevious' ) ] ); // set parent
					jQuery( amsgPrevious ).click( function()
					{ // spark off the "onclick" for original thumb ( ie/ pre-load and display etc )
						jQuery( this ).data( 'amsgParent' ).click();
					});
					jQuery( amsgPrevious ).appendTo( '#amsgScreen' );// add to screen
				}
				if( amsgGallery[ image.data( 'amsgNext' ) ].attr( 'src' ) != image.attr( 'src' ) )
				{
					// build "next" thumb
					var amsgNext = jQuery( '<img class="amsgNext" style="width:80px;" src="'+amsgGallery[ image.data( 'amsgNext' ) ].attr( 'src' )+'" title=" '+jQuery().amsgTranslate('View the next image')+' " />' );
					jQuery( amsgNext ).data( 'amsgParent', amsgGallery[ image.data( 'amsgNext' ) ] ); // set parent
					jQuery( amsgNext ).click( function()
					{ // spark off the "onclick" for original thumb ( ie/ pre-load and display etc )
						jQuery( this ).data( 'amsgParent' ).click();
					});
					jQuery( amsgNext ).appendTo( '#amsgScreen' ); // add to screen
				}
				if( !image.attr( amsgSettings.detailTitle ) )
				{ // no title
					var amsgTitle = jQuery().amsgTranslate( 'Untitled image' );
				}
				else
				{
					var amsgTitle = image.attr( amsgSettings.detailTitle );
				}
				jQuery( '<h3 id="amsgImageTitle"><span title=" ">'+amsgTitle+'</span></h3>' ).appendTo( '#amsgScreen' ); // add image caption ( defaults to "Untitled Image )
				jQuery( '<img id="amsgDetailImage" class="size-'+image.data( 'amsgWidth')+'x'+image.data( 'amsgHeight' )+'" src="'+image.data( 'amsgDetail' )+'" />' ).appendTo( '#amsgScreen' ); // add detailed image ... it's what they came for


				if( image.attr( amsgSettings.detailCaption ) )
				{ // we have a caption
					jQuery( '<p id="amsgImageCaption"><span title=" ">'+image.attr( jQuery().data( 'amsgSettings' ).detailCaption )+'</span></p>' ).appendTo( '#amsgScreen' ); // add caption
				}

				if( amsgSettings.share  )
				{ // we want to share
					amsgSettings.share( image ).appendTo( '#amsgScreen' ); // add share link
				}

				jQuery().amsgResize(); // resize the image ready for display

				// stop clicks on child elements closing screen
				// @todo yabs : should simplify all this crap
				jQuery( '.amsgPrevious' ).click( function(e)
				{
					e.stopPropagation();
				});
				jQuery( '.amsgNext' ).click( function(e)
				{
					e.stopPropagation();
				});
				jQuery( '#amsgImageTitle span' ).click( function(e)
				{
					e.stopPropagation();
				});
				jQuery( '#amsgImageCaption span' ).click( function(e)
				{
					e.stopPropagation();
				});
				jQuery( '#amsgImageLink span' ).click( function(e)
				{
					e.stopPropagation();
				});
				jQuery( '#amsgScreen' ).animate( {opacity:1}, 100 );
			});
		},


		/**
		 * Another highly original named function
		 * this one just "closes" the gallery overlay
		 */
		amsgCloseScreen: function()
		{
			jQuery( 'html' ).removeClass( 'amsgWindowOpen' );
			jQuery( '#amsgScreen' ).empty();
			if( typeof( amsgIsIE ) != 'undefined' )
			{	// IE6 crap
				window.scrollTo( jQuery('body').data('amsgLeft'),jQuery('body').data('amsgTop') );
			}
		},


		/**
		 * Resizes the detail image to suit the current viewport
		 *
		 */
		amsgResize: function()
		{
			if( !jQuery( 'html' ).hasClass( 'amsgWindowOpen' ) )
			{ // window isn't open
				return;
			}

			var amsgObject = jQuery( '#amsgDetailImage' );

			// work out heights && margins of image details
			var amsgChildren = 0;
			if( jQuery( 'h3' ).is( '#amsgImageTitle' ) )
			{ // calculate title height && margins
//				window.alert( jQuery( '#amsgImageTitle' ).outerHeight({margin:true}) );
				amsgChildren += jQuery( '#amsgImageTitle' ).height();
				amsgChildren += Math.round( jQuery('#amsgImageTitle' ).css('marginTop').slice( 0, -2 ) ); // remove "px" and force to "numeric"
				amsgChildren += Math.round( jQuery('#amsgImageTitle' ).css('marginBottom').slice( 0, -2 ) ); // remove "px" and force to "numeric"
						}
			if( jQuery( 'p' ).is( '#amsgImageCaption' ) )
			{ // calculate caption height && margins
				amsgChildren += jQuery( '#amsgImageCaption' ).height() + 45;
			}
			else
			{ // add a tad to move image off bottom of screen
				amsgChildren += 30;
			}
			if( jQuery( 'p' ).is( '#amsgImageLink' ) )
			{ // calculate link height && margins
				amsgChildren += Math.round( jQuery( '#amsgImageLink' ).height() )+45;
			}

			//		amsgChildren += 50; // just for luck ;)
			// set max width/height
			var amsgWindowHeight = jQuery( window ).height() - amsgChildren; // leave space for child elements
			var amsgWindowWidth = jQuery( window ).width() - 200; // leave space for previous/next
			// get image original height / width
			var amsgImageWidth = jQuery( amsgObject ).attr( 'class' ).replace( /size-(.+?)x.+?$/, '$1' );
			var amsgImageHeight = amsgObject.attr('class').replace( /^.+?x(.+?)/, '$1' );
			// set ratio
			var amsgImageRatio = amsgImageWidth / amsgImageHeight;

			if( amsgImageWidth > amsgWindowWidth )
			{ // image is to wide
				amsgImageWidth = amsgWindowWidth;
				amsgImageHeight = amsgImageWidth / amsgImageRatio;
			}

			if( amsgImageHeight > amsgWindowHeight )
			{ // image is to high
				amsgImageHeight = amsgWindowHeight;
				amsgImageWidth = amsgImageHeight * amsgImageRatio;
			}
			// resize the image
			jQuery( amsgObject ).width( Math.round( amsgImageWidth ) ).height( Math.round( amsgImageHeight ) );
			// move previous/next to suit
			jQuery( '.amsgPrevious' ).css( { marginTop: -1 * Math.round( jQuery( '.amsgPrevious' ).height() / 2 ) });
			jQuery( '.amsgNext' ).css( { marginTop: -1 * Math.round( jQuery( '.amsgNext' ).height() / 2 ) });
			if( jQuery( '#amsgDetailImage' ).width() / jQuery( '#amsgDetailImage' ).attr( 'class' ).replace( /size-(.+?)x.+?$/, '$1' ) > .75 )
			{ // pretty well zoomed in now, disable zoom
					jQuery( '#amsgDetailImage' ).unbind( 'mousemove' ).attr( 'title', ' ' ).unbind( 'click' ).click( function(e)
					{
						e.stopPropagation();
					});
					jQuery( '#amsgZoom' ).remove();
			}
			else
			{
				jQuery( '#amsgDetailImage' ).unbind( 'click' ).click( function(e)
				{
					// add zoom ability
					jQuery( this ).unbind('mousemove' ); // we only need triggering once
					jQuery( this ).bind( 'mousemove', function( e )
					{
						jQuery().amsgZoom(e);
					});
					jQuery().amsgZoom(e);
					e.stopPropagation();
				}).attr( 'title',  ' '+jQuery().amsgTranslate( 'Click for zoom mode' )+' ' );
			}
		},


		/**
		 * Adds a zoom box to the image
		 *
		 * @param object e : event
		 */
		amsgZoom: function( e )
		{
			var amsgImageOffset = jQuery( '#amsgDetailImage' ).offset();
			var amsgImageLeft = amsgImageOffset.left;
			var amsgImageTop = amsgImageOffset.top;
			var amsgMouseY =  e.pageY - amsgImageTop;
			var amsgMouseX =  e.pageX - amsgImageLeft;

			if( amsgMouseX < -25 || amsgMouseY < -25 || amsgMouseX > jQuery( '#amsgDetailImage' ).width()+25 || amsgMouseY > jQuery( '#amsgDetailImage' ).height()+25 )
			{ // no longer zooming
				jQuery( '#amsgZoom' ).remove();
				return;
			}

			var amsgOffsetTop = Math.round( ( amsgMouseY  ) / ( jQuery( '#amsgDetailImage' ).height() / 100 ) );
			var amsgOffsetLeft = Math.round( ( amsgMouseX ) / ( jQuery( '#amsgDetailImage' ).width() / 100 ) );

			amsgOffsetTop = ( amsgOffsetTop < 0 ? 0 : ( amsgOffsetTop > 100 ? 100 : amsgOffsetTop ) );
			amsgOffsetLeft = ( amsgOffsetLeft < 0 ? 0 : ( amsgOffsetLeft > 100 ? 100 : amsgOffsetLeft ) );
			var amsgBackgroundOffset = amsgOffsetLeft+'% '+amsgOffsetTop+'%';

			if( !jQuery( 'div' ).is( '#amsgZoom' ) )
			{ // we need to create zoom
				jQuery( '<div id="amsgZoom" style="background-image:url('+jQuery( '#amsgDetailImage' ).attr( 'src' )+' );" title=" '+jQuery().amsgTranslate( 'Click for normal mode' )+' ">&nbsp;</div>' ).appendTo( '#amsgScreen' );
				jQuery( '#amsgZoom' ).bind( 'mousemove', function( e )
				{
					jQuery().amsgZoom( e );
				});
				jQuery( '#amsgZoom' ).click( function(e)
				{
					e.stopPropagation();
					jQuery( '#amsgDetailImage' ).unbind( 'mousemove' );
					jQuery( this ).remove();
				});
			}
			jQuery( '#amsgZoom' ).css({
				backgroundPosition: amsgBackgroundOffset,
				top: (e.clientY )+"px",
				left: (e.clientX )+"px"
			});
		}
	});
}