//------------------------------------------------------------------------------
// functions to fade photos in/out
//
// Basic idea is that all the images occupy the same physical location on the
// screen. Normally only the "current" image is visible. To move backwards or
// forwards, we fade one image out, while simultaneously fading the other in.
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// globals
//------------------------------------------------------------------------------

var nPhotos = 0;		// number of photos
var photos = new Array();	// the set of photos
var curr = -1;			// index of current photo

//------------------------------------------------------------------------------
// setOpacity - cross browser method to set opacity of an image
//------------------------------------------------------------------------------

function setOpacity (img, opacity) {
	opacity = (opacity == 100) ? 99.999 : opacity;
	img.style.filter = "alpha(opacity:" + opacity + ")";	// IE
	img.style.KHTMLOpacity = opacity/100;			// Safari
	img.style.MozOpacity = opacity/100;			// old Moz
	img.style.opacity = opacity/100;			// standard
}

//------------------------------------------------------------------------------
// transition - fade from photo[i] to photo[j]
//
// each call to this function moves the transition along by 10%
//------------------------------------------------------------------------------

var trans_timer = -1			// in case we need to cancel timer
var from, to;				// the from and to photo objects

function transition (i,j) {

	var again = false;

	from = photos[i];
	to = photos[j];

	// trace("transition: " + i + " --> " + j);

	if (from && from.opacity > 0) {
		from.opacity -= 10;
		setOpacity(from.img, from.opacity);
		if (from.opacity == 0)
			from.img.style.display = 'none';
		else
			again = true;
	}

	if (to.opacity < 100) {

		// avoid unnecessary traffic, by only fetching image
		// when its needed

		to.fetch();
		
		to.opacity += 10;
		setOpacity(to.img, to.opacity);
		to.img.style.display = 'block';
		again = true;
	}

	if (again) {
		trans_timer = window.setTimeout('transition(' + i + ',' + j + ')',100);
		return;
	}

	// the transition is finished. If the user has clicked too fast, we
	// can end up with several images with non-zero opacity. We fix this by
	// setting opacity of all but the current to 0.

	trans_timer = -1;

	for (var k=0; k < nPhotos; k++) {

		if (k == j)
			continue;

		if (photos[k].img)
			setOpacity(photos[k].img,0);
	}
}

//------------------------------------------------------------------------------
// abort_transition - abort the in-progress transition effect, if any
//------------------------------------------------------------------------------

function abort_transition ()
{
	if (trans_timer == -1)
		return;

	// trace("abort");

	// kill the timer

	clearTimeout(trans_timer);

	// finish off the transition lickerty-split

	from.opacity = 0;
	setOpacity(from.img,from.opacity);
	from.img.style.display = 'none';

	to.opacity = 100;
	setOpacity(to.img, to.opacity);
	to.img.style.display = 'block';
}

//------------------------------------------------------------------------------
// pshow - show photo[i]
//------------------------------------------------------------------------------

function pshow (i) {

	// ignore if already showing requested image

	if (i == curr)
		return;

	// start the fade=in effect for this photo

	var photo = photos[i];
	photo.fetch();
	transition(curr,i);

	curr = i;

	// show photo name

	var pname = document.getElementById("pname");
	pname.innerHTML = photo.name;

	// show the caption panel

	photo.showCaption();

	// pre-fetch the next photo so that its image will be here by the time
	// user clicks the next time

	photo = photos[i+1];
	if (photo)
		photo.fetch();
}

//------------------------------------------------------------------------------
// pnext - show next photo
//------------------------------------------------------------------------------

function pnext () {

	abort_transition();
	pshow((curr+1) >= nPhotos ? 0 : curr + 1);
}

function pnextf () {
    pnext();
    abort_transition();
}

//------------------------------------------------------------------------------
// pprev - show prev photo
//------------------------------------------------------------------------------

function pprev () {
	abort_transition();
	pshow((curr-1) < 0 ? nPhotos -1 : curr - 1);
}

function pprevf () {
    pprev();
    abort_transition();
}

//------------------------------------------------------------------------------
// pslideshow - show photos as a slide show
//------------------------------------------------------------------------------

var slideshow_timer = -1;

function pnextslide () {
	pnext();
	slideshow_timer = window.setTimeout('pnextslide()',5000);
}

function pslideshow (start) {

	var pb = document.getElementById("pbuttons");

	if (start) {
		abort_transition();
		pnextslide();

		pb.innerHTML = '<a href="javascript:pslideshow(false);">Stop</a>';
	}
	else {
		pb.innerHTML = '<a href="javascript:pprevf();"> Prev </a>'
    		 + '| <a href="javascript:pnextf();"> Next </a>'
    		 + '| <a href="javascript:pslideshow(true);"> Start Slide Show </a>';
	
		clearTimeout(slideshow_timer);
	}
}

//------------------------------------------------------------------------------
// photo object, used in gallery page
//------------------------------------------------------------------------------

function fetch () {	// fetch the image for this photo

	// we may have previously fetched this photo

	if (this.fetched)
		return;

	trace("fetch " + this.url);

	this.img = new Image();
	this.img.src = this.url;

	this.opacity = 0;

	var pimage = document.getElementById("pimage");
	pimage.appendChild(this.img);

	this.fetched = true;
}

var caption_req;

function showCaption () {	// fetch and display the caption file
	var url = this.caption;
	caption_req = createRequest();
        http_get(caption_req,url,"",handleCaptionResponse);
}

function handleCaptionResponse() {

	if (caption_req.readyState != 4)
		return;

	if (caption_req.status != 200)
		return;

	var pcaption = document.getElementById("pcaption");
	pcaption.innerHTML = caption_req.responseText;
}


function Photo (index, dir, name, caption)
{
	this.index = index;
	this.opacity = 0;
	this.fetched = false;
	this.name = name;
	this.caption = '/' + dir + '/' + caption;
	this.url = '/images/' + dir + '/' + name;

	// object methods

	this.fetch = fetch;
	this.showCaption = showCaption;

	// alert("created Photo " + index + ', with url: ' + this.url);
}

//------------------------------------------------------------------------------
// psetv - set the vertical size of the pframe
//------------------------------------------------------------------------------

function psetv (new_h) {
	var pwrapper = document.getElementById('pwrapper');
	pwrapper.style.height = new_h + 'px';
}

//------------------------------------------------------------------------------
// pinit - initialize photo display. Gets list of photos and caption data
//------------------------------------------------------------------------------

var list_req;
var curr_gallery;

function pinit (gallery_name) {

	// fetch data from server

	curr_gallery = gallery_name;

	var url = "/fetch_photo_list?gallery=" + curr_gallery + '-json';

	list_req = createRequest();
        http_post(list_req,url,"",handlePinitResponse);
}

//------------------------------------------------------------------------------
// handlePinitResponse - process the list of photos
//------------------------------------------------------------------------------

function handlePinitResponse() {

        if (list_req.readyState == 4) {

                // alert('got response: ' + list_req.responseText);
                // alert('got status:   ' + list_req.statusText);

                if (list_req.status == 200) {
			var result = eval('(' + list_req.responseText + ')');
			var pdata = result.pdata;

			// load the photo data

			for (i=0; i<pdata.length; i++) {
				photos[nPhotos++] =
					new Photo(i,curr_gallery,pdata[i].name,pdata[i].caption);
			}

			// and show the first photo

			pnext();
                }
        }
}

//------------------------------------------------------------------------------
// startList - setup the "li" hover for IE
//------------------------------------------------------------------------------

startList = function () {
    if (document.all && document.getElementById) {
	var navRoot = document.getElementById("mbroot");
	for (i=0; i<navRoot.childNodes.length; i++) {
	    var node = navRoot.childNodes[i];
	    if (node.nodeName=="LI") {
		node.onmouseover = function() {
		    this.className += " over";
		}
		node.onmouseout = function() {
		    this.className = this.className.replace(" over", "");
		}
	    }
	}
    }
}

//------------------------------------------------------------------------------
// on page load, do some initialization
//------------------------------------------------------------------------------

window.onload = startList;

//------------------------------------------------------------------------------
// trace - show debug message if possible
//
// To use, put something like the following in your html:
//
//  <form><textarea id='trace' cols=80 rows=12></textarea></form>
//
// the message text will be appended to this text area
//------------------------------------------------------------------------------

function trace (text) {

        var msg = document.getElementById('trace');

        if (!msg)
                return;

        msg.value = msg.value + text + '\n';
}

function ntrace (text) {

        var msg = document.getElementById('trace');

        if (!msg)
                return;

        msg.value = msg.value + text + '  ';
}

//------------------------------------------------------------------------------
// createRequest - creates an XMLHttpRequest object
//------------------------------------------------------------------------------

function createRequest () {
        var req;

	if (window.XMLHttpRequest) {			// Mozilla, Safari, ...
		req = new XMLHttpRequest();
	} else if (window.ActiveXObject) {		// IE
		try {
			req = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e) {
			try {
				req = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (e) {}
		}
	}

	if (!req) {
		alert('Error: unable to create XMLHTTP instance');
		return null;
	}

        return req;
}

//------------------------------------------------------------------------------
// http_post - post data to an url using XMLHttpRequest
//------------------------------------------------------------------------------

function http_post (req, url, data, callback) {

	// alert("http_post: " + req.readyState + ", " + url + ", " + data);

	// avoid posting if already in use

	if (req.readyState == 0 || req.readyState == 4) {
		req.open('POST',url,true);
		req.setRequestHeader("Content-Type",
			"application/x-www-form-urlencoded");
		req.onreadystatechange = callback;
		req.send(data);
	}
}

//------------------------------------------------------------------------------
// http_get - fetch url using XMLHttpRequest
//------------------------------------------------------------------------------

function http_get (req, url, data, callback) {

	// alert("http_get: " + req.readyState + ", " + url + ", " + data);

	// avoid get if already in use

	if (req.readyState == 0 || req.readyState == 4) {
		req.open('GET',url,true);
		req.onreadystatechange = callback;
		req.send(null);
	}
}

//------------------------------------------------------------------------------
// replace_main - replace main panel content
//------------------------------------------------------------------------------

function replace_main (url) {

	var data = "";

	// alert("post data = " + data);

	var panel = document.getElementById('main_panel');
	panel.innerHTML = "";

	var url = "/list_photos";

	main_req = createRequest();
        http_post(main_req,url,data,handleMainResponse);
}

