// JavaScript Document

//
// Creates a photgraph gallery in DHTML showing a main image and a set of thumbnail images.
// The set of photographs is loaded from an XML file.
//
// PAGE ELEMENTS REQUIRED
// The functions expect to be able to locate the following Elemnets by ID in the document.
// 
// GalleryMainImage -- an Image Element used to show the main image.
//
// GalleryMainImageContainer -- The element containing the main image, such as a DIV.
//

function log( info )
{
	if(window.console) {
		window.console.log(info);
	} 
}

function fReport(oSelf, sAction, oArguments) { 
	if(window.console) {
		window.console.log(' - Called "' + sAction + '" with arguments: (' + oArguments + ')');
	} 
}


function Photograph()
{
	this.hosthref = null;
	this.homehref = null;
	this.hostid = null;
	this.title = null;
	this.images = new Array();
}

Photograph.prototype.parseXml = function ( photo )
{
	this.hosthref = photo.getAttribute("hosthref");
	this.homehref = photo.getAttribute("homehref");
	this.hostid = photo.getAttribute("hostid");
	this.title = photo.getAttribute("title");
	this.bestCaptureTime = photo.getAttribute("bestCaptureTime");
	this.images = new Array();
	
	var images = photo.getElementsByTagName("img");
	//for( var i in images )
	for( var i = 0; i < images.length; ++i )
	{
		var img = images[i];
		if( img.attributes )
		{
			//log( "img: " + img );
			var image = {};
			image.src = img.getAttribute("src"); //.textContent;
			image.width = parseInt( img.getAttribute("width"));
			image.height = parseInt( img.getAttribute("height"));
			//log( image );
			this.images.push( image );
		}
	}
	
	this.iptc = {};

	if( photo.getElementsByTagName("IPTC").length > 0 )
	{
		var xiptc = photo.getElementsByTagName("IPTC")[0];
		this.iptc.CiEmailWork = xiptc.getAttribute("ciEmailWork");
		this.iptc.SubLocation = xiptc.getAttribute("subLocation");
		this.iptc.City = xiptc.getAttribute("city");
		this.iptc.State = xiptc.getAttribute("state");
		this.iptc.Country = xiptc.getAttribute("country");
		this.iptc.CopyrightNotice = xiptc.getAttribute("copyrightNotice");
		this.iptc.RightsUsageTerms = xiptc.getAttribute("rightsUsageTerms");
		
		var creators = xiptc.getElementsByTagName("creator");
		this.iptc.Creator = "";
		if( creators.length > 0 )
		{
			for( var c = 0; c < creators.length; ++c )
			{
				var creator = creators[c];
				if( c > 0 )
				{
					this.iptc.Creator += ", ";	
				}
				this.iptc.Creator += creator.textContent;
				
			}
		}
		
		this.iptc.Description = "";
		if( xiptc.getElementsByTagName("description").length > 0 )
		{
			this.iptc.Description = xiptc.getElementsByTagName("description")[0].textContent;
		}
		
		this.iptc.keywords = [];
	
		if( xiptc.getElementsByTagName("keywords").length > 0 )
		{
			var keywords = 	xiptc.getElementsByTagName("keywords")[0].getElementsByTagName("keyword");
			for( var k = 0; k < keywords.length; ++k )
			{
				var keyword = keywords[k].textContent;
				this.iptc.keywords.push( keyword );
			}
		}
		
	}
		
	/*
	<CameraMetadata makeModel="Nikon D200" fStop="f/8" shutterSpeed="1/250" iso="100" lens="105.0 mm f/2.8" focalLength="105mm"/>
	*/
	if( photo.getElementsByTagName("CameraMetadata").length > 0 )
	{
		this.cameraMetadata = {};
		var camerax = photo.getElementsByTagName("CameraMetadata")[0];
		
		this.cameraMetadata.makeModel = camerax.getAttribute("makeModel");
		this.cameraMetadata.fStop = camerax.getAttribute("fStop");
		this.cameraMetadata.shutterSpeed = camerax.getAttribute("shutterSpeed");
		this.cameraMetadata.iso = camerax.getAttribute("iso");
		this.cameraMetadata.lens = camerax.getAttribute("lens");
		this.cameraMetadata.focalLength = camerax.getAttribute("focalLength");
		
		
	}

}



Photograph.prototype.getBestImageSize = function( longestSide )
{
	log("getBestImageSize in " + longestSide );
	
	if( longestSide >= 1024 && longestSide < 1600 )
	{
		log("constraining longestSide to 1024");
		longestSide = 1024;
	}
	
	var best = null;
	var bestSize = null;
	var largestAvailable  = null;
	var lagestAvailableMax;
	for( var i in this.images )
	{
		var image = this.images[i];
		var max = Math.max( image.width, image.height );
		
		if( max >= longestSide )
		{
			if( (best == null) || (max < bestSize) )
			{
				best = image;
				bestSize = max;
			}
		}
		
		if( largestAvailable == null || ( max > lagestAvailableMax ) )
		{
			lagestAvailableMax = max;
			largestAvailable = image;
		}
	}
	if( best == null )
	{
		best = largestAvailable;
	}
	//all images
	return best;
}

function Gallery( photoXmlPath )
{
	// configurable parameters
	this.thumbnailLoadSize = 6;
	this.thumbnailSize = 100;
	this.standardMargin = 10;
	if( photoXmlPath == null )
	{
		this.photoXmlUrl = "photographs.xml";
	} else {
		this.photoXmlUrl = photoXmlPath;
	}
	
	log( "photoXmlUrl: " + photoXmlPath );
	
	//  internal variables
	this.started = false;
	this.firstLoad = true;
	this.thumbnailsLoaded = 0;
	this.thumbnailIndex = -1;
	this.xml = null;
	this.photographs = null;
	this.curPreviewPhotograph =  null;
	this.setName = "";
	this.changeDocumentTitle = true;
	
	this.onLoaded = function() {
		log("Gallery Loaded");	
	}
}


Gallery.prototype.start = function()
{
	this.started = true;
	fReport(this, "gallery.start", "Hi!");
	if (!document.getElementById || !document.createElement || !document.appendChild) return false;
	
	// initially one batch of thumbnails is loaded already
	this.thumbnailsLoaded = this.thumbnailLoadSize;
	
	
	
	//PxUtils.showHideElementById("GalleryMainImage", false );
	
	PxUtils.showHideElementById("GalleryNavPrev", false );
	PxUtils.showHideElementById("GalleryNavNext", true );
	
	PxUtils.showHideElementById("GalleryThumbPrevNav", false );
	PxUtils.showHideElementById("GalleryThumbAdvaceNav", false );
	
	this.getXml();
	
	
	
}




Gallery.prototype.getXml = function()
{
	//var oXMLHttpRequest = new XMLHttpRequest;
	var oXMLHttpRequest = PxUtils.createXmlHTTPRequest();
	
	if( oXMLHttpRequest == null ) return;
	
	oXMLHttpRequest.gallery = this;
	
	oXMLHttpRequest.open("GET", this.photoXmlUrl, true);
	oXMLHttpRequest.onreadystatechange = function() {
		//if (this.readyState == XMLHttpRequest.DONE) {
		if (this.readyState == 4 ) {
		   fReport( this, "DONE", this.responseText ); 
		
			this.gallery.xml = this.responseXML;
		
			this.gallery.parseXml();
			
		}
	}
	oXMLHttpRequest.send(null); 
}

Gallery.prototype.parseXml = function()
{
	if( this.xml )
	{
		this.photographs = new Array();
		var photos = this.xml.getElementsByTagName("Photograph");
		
		var sets = this.xml.getElementsByTagName("photographs");
		if( sets )
		{
			var set = sets[0];
			this.setName = set.getAttribute("setName");
			
			if( this.setName && this.changeDocumentTitle )
			{
				document.title = "Pixel-And-Ink: " + this.setName;	
			}
		}
		
		log("num photographs: " + photos.length );
		//for( var p in photos )
		for( var p = 0; p < photos.length; ++p )
		{
			var photo = photos[p];
			if(  photo.attributes )
			{
				//log( p + " " + photo );
				var photograph = new Photograph();
				//hosthref="null" homehref="null" hostid="flickr::3331874843" title="20090305DEF_D2000859.web"
				photograph.hosthref = photo.getAttribute("hosthref");
				photograph.homehref = photo.getAttribute("homehref");
				photograph.hostid = photo.getAttribute("hostid");
				photograph.title = photo.getAttribute("title");
				photograph.images = new Array();
				
				var images = photo.getElementsByTagName("img");
				//for( var i in images )
				for( var i = 0; i < images.length; ++i )
				{
					var img = images[i];
					if( img.attributes )
					{
						//log( "img: " + img );
						var image = {};
						image.src = img.getAttribute("src"); //.textContent;
						image.width = parseInt( img.getAttribute("width"));
						image.height = parseInt( img.getAttribute("height"));
						//log( image );
						photograph.images.push( image );
					}
				}
				
				//log( photograph );
				this.photographs.push( photograph );
			}

		}
		
		
		var firstPhotograph = this.photographs[0];
		log( "firstPhotograph: " + firstPhotograph.hostid );
		this.showPhotograph(firstPhotograph.hostid, true );
		
		
		PxUtils.showHideElementById("GalleryThumbPrevNav", false );
		PxUtils.showHideElementById("GalleryThumbAdvaceNav", true );
		
		
		
		
	}
	//null check
}
//parse xml



Gallery.prototype.findPhotographById = function( id )
{
	var photograph;
	if( this.photographs )
	{
		for( var p in this.photographs )
		{
			var next = this.photographs[p];
			if( next.hostid == id )
			{
				photograph = next;
				break;
			}
		}
	}
	return photograph;

}


Gallery.prototype.findPhotographIndex = function( photograph )
{
	var index;
	if( this.photographs )
	{
		for( var p in this.photographs )
		{
			var next = this.photographs[p];
			if( next.hostid == photograph.hostid )
			{
				index = p;
				break;
			}
		}
	}
	return index;

}



Gallery.prototype.getBestImageSize = function(photograph, longestSide )
{
	log("getBestImageSize in " + longestSide );
	
	if( longestSide >= 1024 && longestSide < 1600 )
	{
		log("constraining longestSide to 1024");
		longestSide = 1024;
	}
	
	var best = null;
	var bestSize = null;
	var largestAvailable  = null;
	var lagestAvailableMax;
	for( var i in photograph.images )
	{
		var image = photograph.images[i];
		var max = Math.max( image.width, image.height );
		
		if( max >= longestSide )
		{
			if( (best == null) || (max < bestSize) )
			{
				best = image;
				bestSize = max;
			}
		}
		
		if( largestAvailable == null || ( max > lagestAvailableMax ) )
		{
			lagestAvailableMax = max;
			largestAvailable = image;
		}
	}
	if( best == null )
	{
		best = largestAvailable;
	}
	//all images
	return best;

}

Gallery.FitLogic = function( image, boxSize, allowEnlarge )
{
	log( "fitToBox fitting: " + image.width + "x" + image.height + " in " + boxSize.width + "x" + boxSize.height );
	var fitSize = {width: image.width, height: image.height };
	
	var overWidth = image.width / boxSize.width;
	var overHeight = image.height / boxSize.height;
	
	log( "overWidth: " + overWidth + " overHeight: "  + overHeight)
	
	// too big case
	if( overWidth > 1.0 || overHeight > 1.0 )
	{
		var resizeRatio = 1.0;
		if( overWidth >= overHeight )
		{
			log("...too wide");
			resizeRatio = boxSize.width / image.width;
		} else {
			log("...too tall");
			resizeRatio = boxSize.height / image.height;
		}
		
		log( "resizeRatio : " + resizeRatio);
		
		fitSize.width = Math.round(image.width * resizeRatio);
		fitSize.height = Math.round(image.height * resizeRatio);
		
	} else if( (overWidth < 1.0 || overHeight < 1.0) && allowEnlarge ) {
		var resizeRatio = 1.0;
		if( overWidth <= overHeight )
		{
			resizeRatio = boxSize.width / image.width;
		} else {
			resizeRatio = boxSize.height / image.height;
		}
		log( "resizeRatio : " + resizeRatio);
		
		fitSize.width = Math.round(image.width * resizeRatio);
		fitSize.height = Math.round(image.height * resizeRatio);
		
	
	}
	return fitSize;
}

Gallery.prototype.fitToBox = function( image, boxSize, allowEnlarge )
{
	log( "fitToBox fitting: " + image.width + "x" + image.height + " in " + boxSize.width + "x" + boxSize.height );
	var fitSize = {width: image.width, height: image.height };
	
	var overWidth = image.width / boxSize.width;
	var overHeight = image.height / boxSize.height;
	
	log( "overWidth: " + overWidth + " overHeight: "  + overHeight)
	
	// too big case
	if( overWidth > 1.0 || overHeight > 1.0 )
	{
		var resizeRatio = 1.0;
		if( overWidth >= overHeight )
		{
			log("...too wide");
			resizeRatio = boxSize.width / image.width;
		} else {
			log("...too tall");
			resizeRatio = boxSize.height / image.height;
		}
		
		log( "resizeRatio : " + resizeRatio);
		
		fitSize.width = Math.round(image.width * resizeRatio);
		fitSize.height = Math.round(image.height * resizeRatio);
		
	} else if( (overWidth < 1.0 || overHeight < 1.0) && allowEnlarge ) {
		var resizeRatio = 1.0;
		if( overWidth <= overHeight )
		{
			resizeRatio = boxSize.width / image.width;
		} else {
			resizeRatio = boxSize.height / image.height;
		}
		log( "resizeRatio : " + resizeRatio);
		
		fitSize.width = Math.round(image.width * resizeRatio);
		fitSize.height = Math.round(image.height * resizeRatio);
		
	
	}
	return fitSize;
}

Gallery.prototype.maxVisiblePreviewSize = function()
{
		var previewBox = document.getElementById("GalleryMainImageContainer");
		if( previewBox )
		{
			var size = {};
			//if( ! window.innerWidth )
			//{
				
			size.width = previewBox.clientWidth - (this.standardMargin * 2); // less the border on the photo
			size.height  = previewBox.clientHeight - (this.standardMargin * 2); // - <?= $thumbnailStripHeight ?>;
			
			return size;
		}
}




Gallery.prototype.showPhotograph = function( id, isFirst )
{
	var photograph = this.findPhotographById(id);
	log("showPhotograph: " + photograph.hostid );
	if( photograph )
	{
		log( "show photograph: " + photograph );
		this.curPreviewPhotograph = photograph;
		
		var visiblePreviewSize = this.maxVisiblePreviewSize();
		var sizeToGet = visiblePreviewSize;
		log( "visiblePreviewSize: " + visiblePreviewSize.width + "x" + visiblePreviewSize.height );
		
		var bestSize = this.getBestImageSize( photograph, Math.max(sizeToGet.width, sizeToGet.height) );
		
		if( !bestSize )
		{
			throw new Error("getBestImageSize reutnred null?");
		}
		
		this.curPreviewImage = bestSize;
		
		log( "best size to show: " + this.curPreviewImage.width + "x" + this.curPreviewImage.height );
		
		var fitSize = this.fitToBox( this.curPreviewImage, visiblePreviewSize );
		log( "fitSize: " + fitSize.width + " x " + fitSize.height );

		var previewElement = document.getElementById("GalleryMainImage");
		
		this.isLoading = true;
		this.currentId = id;
		
		if( ! isFirst )
		{
			PxUtils.showHideElementById( "GalleryLoaderFloater", true );
		}
		
		
		var offscreenPreview = new Image( fitSize.width, fitSize.height );
		
		this.offscreenPreview = offscreenPreview;
		offscreenPreview.src = this.curPreviewImage.src;
		log( "offscreenPreview.src: " + offscreenPreview.src );
		
		if( offscreenPreview.complete )
		{
			this.onPreviewLoaded();
		} else {
			// the HTML page must define this function, and it must call the onPreviewLoaded for the gallery instance
			offscreenPreview.onload = onGalleryImageLoaded;
		}
		
		var photoNumber = this.findPhotographIndex( this.curPreviewPhotograph );
		photoNumber = parseInt( photoNumber ) + 1;
		var indexInfo = "<b>" + this.setName + "</b> " + photoNumber + " of " + this.photographs.length;
		var titleInfo = "<b>" + this.curPreviewPhotograph.title + "</b>"
		if( this.curPreviewPhotograph.hosthref )
		{
			titleInfo += "&nbsp;<a href='" + this.curPreviewPhotograph.hosthref  + "'>" + "photo info..." + "</a>";	
		} else {
			log("Photograph has no hostref?");	
		}
		log("title info: " + titleInfo );
		
		var galleryIndexText = document.getElementById("GalleryIndexText");
		if( galleryIndexText )
		{
			galleryIndexText.innerHTML = (indexInfo + ",&nbsp;" + titleInfo);
		}
		
		
	}
}

Gallery.prototype.onPreviewLoaded = function(  )
{
	log("onPreviewLoaded");
	this.isLoading = false;
	
	//var loaderFloater = document.getElementById("loaderFloater");
	//loaderFloater.style.visibility = "hidden";
	
	PxUtils.showHideElementById( "GalleryLoaderFloater", false );
	
	PxUtils.showHideElementById("GalleryMainImage", true );
	
	if( this.offscreenPreview )
	{
		this.isLoading = false;
		var previewElement = document.getElementById("GalleryMainImage");
		
		if( previewElement )
		{
			// Show the new image in the preview window
			previewElement.setAttribute("width", this.offscreenPreview.width );
			previewElement.setAttribute("height", this.offscreenPreview.height );
			//previewElement.setAttribute("src", this.offscreenPreview.src );
			PxAnimateOpactiy.FadeInImage("GalleryMainImage", this.offscreenPreview.src, 10, 50 );
			//id, src, numSteps, delay
		}
		
		
		//gallery.enablePreviewNav();
		
		if( this.firstLoad )
		{
			this.setThumbnailIndex(0);
			this.firstLoad = false;
			this.onLoaded();
		}
		
	}
	//check for null preview
}

Gallery.prototype.nextPhoto = function()
{
	if( this.isLoading )
	{
		
		return;
	}
	
	if( this.curPreviewPhotograph == null ) return;
	
	var index = this.findPhotographIndex( this.curPreviewPhotograph );
	
	++index;
	
	if( index < this.photographs.length )
	{
	
		var nextPhoto = this.photographs[index];
	
		this.showPhotograph( nextPhoto.hostid );
		
		this.setThumbnailIndex( index );
	}
}

Gallery.prototype.prevPhoto = function()
{
	if( this.isLoading )
	{
		
		return;
	}
	
	if( this.curPreviewPhotograph == null ) return;
	
	var index = this.findPhotographIndex( this.curPreviewPhotograph );
	
	--index;
	
	if( index >= 0 )
	{
	
		var nextPhoto = this.photographs[index];
	
		this.showPhotograph( nextPhoto.hostid );
		
		this.setThumbnailIndex( index );
	}
	
	
}

Gallery.prototype.advanceThumbnails = function()
{
	if( this.photographs == null ) return;
	
	var newThumbnailIndex = this.firstThumbnailIndex + this.thumbnailLoadSize;
	// don't go beyond the end
	newThumbnailIndex = Math.min( newThumbnailIndex, (this.photographs.length - this.thumbnailLoadSize));
	
	this.setThumbnailIndex( newThumbnailIndex );
}

Gallery.prototype.reverseThumbnails = function()
{
	if( this.photographs == null ) return;
	
	var newThumbnailIndex = this.firstThumbnailIndex - this.thumbnailLoadSize;
	// don't go beyond the end
	newThumbnailIndex = Math.max( newThumbnailIndex, 0);
	
	this.setThumbnailIndex( newThumbnailIndex );
}


Gallery.prototype.setThumbnailIndex = function( newThumbnailIndex )
{
	// change the src  for all the thumbs to the new URLs
	
	var actualImageIdx = newThumbnailIndex;
	// adjust the index so that the last picture in photographs is always in the last thumbnail slot.
	var lastGoodIdx = (this.photographs.length - this.thumbnailLoadSize);
	if( newThumbnailIndex >  lastGoodIdx)
	{
		newThumbnailIndex = lastGoodIdx;
	}
	
	
	var selection = this.photographs.slice( newThumbnailIndex, (newThumbnailIndex + this.thumbnailLoadSize) );
	
	var thumbnailTable = document.getElementById("GalleryThumbnailTable");
	var thumbnailImages = thumbnailTable.getElementsByTagName("img");
	
	if( thumbnailImages.length == 0 )
	{
		var row = thumbnailTable.insertRow(0);
		for( var c = 0; c < this.thumbnailLoadSize; ++c )
		{
			var td = row.insertCell(0);
			
			var thumbnailImg = new Image();
			thumbnailImg.src = null;
			thumbnailImg.width = this.thumbnailSize;
			thumbnailImg.height = this.thumbnailSize;
			thumbnailImg.id = null;
			thumbnailImg.setAttribute("class","GalleryThumbnalImage");
			
			PxUtils.addEvent( thumbnailImg, "click", onThumbnailClick );
			
			td.appendChild( thumbnailImg );
		}
	}
	
	thumbnailImages = thumbnailTable.getElementsByTagName("img");
	
	// skip the first and last img elemennts -- they are nav buttons
	//for( var i = 1; i < thumbnailImages.length -1; ++i )
	for( var i = 0; i < thumbnailImages.length; ++i )
	{
		var thumbnailImg = 	thumbnailImages[i];
		
		if( i < selection.length )
		{
		
			var photograph = selection[i];
			var thumbSize = Math.max( this.thumbnailSize, 100 ); // limit to 100 so we don't get Flickr's small, square thumbnails
			var image = this.getBestImageSize(photograph, thumbSize );
			var cellSize = {width: this.thumbnailSize,height: this.thumbnailSize};
			var size = this.fitToBox( image, cellSize, false );
			
			thumbnailImg.src = image.src;
			thumbnailImg.width = size.width;
			thumbnailImg.height = size.height;
			thumbnailImg.id = photograph.hostid;
		}
	}
	
	this.firstThumbnailIndex = newThumbnailIndex;
	
	//var showAdvance = this.firstThumbnailIndex < (this.photographs.length - 1);
	//var showReverse = this.firstThumbnailIndex > 0;
	
	var showAdvance = actualImageIdx < (this.photographs.length - 1);
	var showReverse = actualImageIdx > 0;
	
	
	PxUtils.showHideElementById("GalleryNavPrev", showReverse );
	PxUtils.showHideElementById("GalleryNavNext", showAdvance );
	
	var showThumbAdvance = this.firstThumbnailIndex < (this.photographs.length - this.thumbnailLoadSize);
	var showThumbReverse = this.firstThumbnailIndex > 0;
	
	PxUtils.showHideElementById("GalleryThumsbReverseNav", showThumbReverse );
	PxUtils.showHideElementById("GalleryThumsbAdvanceNav", showThumbAdvance );
	
}

Gallery.prototype.onThumbnailClick = function(imageElement)
{
	log( "click on image: " + imageElement.id );
	
	if( ! this.isLoading )
	{
			
		
		if( this.photographs )
		{
			this.showPhotograph( imageElement.id );	
		}
	}
}

Gallery.prototype.fitPreview = function()
{
	
	var visiblePreviewSize = this.maxVisiblePreviewSize();
	
	log( "visiblePreviewSize: " + visiblePreviewSize.width + "x" + visiblePreviewSize.height );
		
	var previewElement = document.getElementById("GalleryMainImage");
		
	if( previewElement )
	{
		var sourceImage = previewElement;
	
		if( this.curPreviewPhotograph )
		{
			
			var bestImage = this.getBestImageSize(
				this.curPreviewPhotograph, 
				Math.max(visiblePreviewSize.width, visiblePreviewSize.height) );
			
			log("bestImage: " + bestImage.width + "x" + bestImage.height );
			
			if( bestImage.src != previewElement.src )
			{
				log("replacing preview with better size: " + bestImage.width + "x" + bestImage.height + " image");
				this.showPhotograph( this.curPreviewPhotograph.hostid );
				return;
			} else {
				sourceImage = this.curPreviewImage;
			}
			
			
			
		} else {
			log( "fit image with no curPreviewPhotograph set -- first time?");
		}
		
		var fitSize = this.fitToBox( sourceImage, visiblePreviewSize, false);
		
		log( "fitSize: " + fitSize.width + " x " + fitSize.height );
		previewElement.setAttribute("width", fitSize.width );
		previewElement.setAttribute("height", fitSize.height );
	}
}

