// -----------------------------------------------------------------------------------
// 
// This page coded by Scott Upton
// http://www.uptonic.com | http://www.couloir.org
//
// This work is licensed under a Creative Commons License
// Attribution-ShareAlike 2.0
// http://creativecommons.org/licenses/by-sa/2.0/
//
// Associated APIs copyright their respective owners
//
// -----------------------------------------------------------------------------------
// --- version date: 02/02/07 --------------------------------------------------------


var menuViz = false;
// CSS border size x 2
var borderSizeDefault = 2*30;
var borderSize = borderSizeDefault;

PhotoVars.currentAlbum = '';
PhotoVars.title = '';
PhotoVars.photoDir = '';
PhotoVars.photoArray = new Array(); // change to null
PhotoVars.numPhotos = 0;
    
PhotoVars.setPhotoArray = function(photoArrayName) {
    if (photoArrayName == '') {photoArrayName = PhotoVars.defaultAlbum;}
    PhotoVars.currentAlbum = photoArrayName;
    PhotoVars.title = allPhotos[photoArrayName].title;
    PhotoVars.photoDir = allPhotos[photoArrayName].photoDir;
    PhotoVars.photoArray = allPhotos[photoArrayName].photoArray;
    PhotoVars.numPhotos = PhotoVars.photoArray.length;
};


/*--------------------------------------------------------------------------*/

// Misc. functions
var Misc = {

    // Parse the input URL
    parseURL: function (URL) {
        var splitURL = URL.split("#");
        // Set default values if no photo or galllery requested
        if (splitURL == URL) {
            PhotoVars.currentAlbum = PhotoVars.defaultAlbum;
            PhotoVars.photoId = 0;
        } 
        // Determine if photo and/or gallery requested 
        else {
            // splitURL[1] should be of the form 'gallery_photonum' or 'gallery' or 'photonum'
            var splitArgs = splitURL[1].split("_");
            // CASE 1: both gallery and photonum requested
            if (splitArgs.length == 2) {
                // check that the gallery is valid
                if (!(Misc.isObject(allPhotos[splitArgs[0]]))) {
                    PhotoVars.currentAlbum = PhotoVars.defaultAlbum;
                    PhotoVars.photoId = 0;
                }
                // check that the requested photo number is an integer and is valid for that gallery.
                else if ( (!(Misc.isInt(PhotoVars.photoId))) && 
                          (!(splitArgs[1] < allPhotos[splitArgs[0]].photoArray.length + 1 && 
                             splitArgs[1] > -1)) ) {
                    PhotoVars.currentAlbum = splitArgs[0];
                    PhotoVars.photoId = 0;
                }
                else {
                    PhotoVars.photoId = splitArgs[1] - 1;
                    PhotoVars.currentAlbum = splitArgs[0];
                }
            }
            else if (splitArgs.length == 1) {
                // CASE 2: only photonum is specified 
                if (Misc.isInt(splitArgs[0])) {
                    // check that the nubmer is in range
                    var photonum = splitArgs[0] - 1;
                    if (photonum < allPhotos[PhotoVars.defaultAlbum].photoArray.length && 
                        photonum > 0) {
                        PhotoVars.photoId = photonum;
                    }
                    else {
                        PhotoVars.photoId = 0;
                    }
                    PhotoVars.currentAlbum = PhotoVars.defaultAlbum;
                }
                // CASE 3: only gallery is specified
                else {
                    // check that gallery is valid
                    if (Misc.isObject(allPhotos[splitArgs[0]])) {
                        var gallery = splitArgs[0]
                        PhotoVars.currentAlbum = gallery; // this doesn't get set!
                    }
                    else {
                        PhotoVars.currentAlbum = PhotoVars.defaultAlbum;
                    }
                    PhotoVars.photoId = 0;
                }
            }
            // CASE 4: doesn't match either of the above cases; use defaults
            else {
                PhotoVars.currentAlbum = PhotoVars.defaultAlbum;
                PhotoVars.photoId = 0;
            }
        }
    },
    
    // Set href suffix (in browser) to point to the current photo, e.g. '#olympic_1'
    setHref: function() {
        var URL = document.location.href.split("#")[0];
        var currentGallery  = PhotoVars.currentAlbum;
        var currentPhotoNum = myPhoto.photoId;
        if (!(currentGallery == PhotoVars.defaultAlbum) && !(currentPhotoNum == 0)) { 
            URL += "#" + currentGallery + "_" + currentPhotoNum;
        }
        else if ((currentGallery == PhotoVars.defaultAlbum) && !(currentPhotoNum == 0)) { 
            URL += "#" + currentPhotoNum;
        }
        else if (!(currentGallery == PhotoVars.defaultAlbum) && (currentPhotoNum == 0)) { 
            URL += "#" + currentGallery;
        }
        document.location.href = URL;
    },
    
    setPageTitle: function() {
        //alert("tester");
        document.title = "EigenPhoto - " + PhotoVars.photoArray[this.photoId][3];
    },
    
    // Create HTML list of galleries
    generateGalleryList: function() {
        // Remove previous list
        Misc.removeGalleryList()
        // Generate list of galleries
        var groups = [];
        for (gallery in allPhotos) {
            groups.push(allPhotos[gallery].group);
        }
        groups = Misc.uniqueArray(groups);
        var galTable = document.createElement('table');
        var galTBody = document.createElement('tbody');
        galTable.id = "galleryList";
        var galTR_spacer = []; var galTR = []; var galTD0 = []; var galTD1 = []; var i = 0;
        for (g=0; g<groups.length; g++) {
            currentgroup = groups[g];
            galTR_spacer[g] = document.createElement('tr');
            galTR_spacer[g].className = "spacer";
            galTBody.appendChild(galTR_spacer[g]); //tbody is requried by IE6 
            for (gallery in allPhotos) {
                if (allPhotos[gallery].group == currentgroup) {
                    numPhotos = allPhotos[gallery].length;
                    year = allPhotos[gallery].year;
                    // calculate year range
                    var yearMin = 10000; var yearMax = 0;
                    for (i=0; i<allPhotos[gallery].photoArray.length; i++) {
                        if (allPhotos[gallery].photoArray[i][4] < yearMin) {
                            yearMin = allPhotos[gallery].photoArray[i][4];
                        }
                        if (allPhotos[gallery].photoArray[i][4] > yearMax) {
                            yearMax = allPhotos[gallery].photoArray[i][4];
                        }
                    }
                    if (yearMin == yearMax) {
                        var year = yearMax + '';
                    }
                    else {
                        var year = yearMin + '-' + yearMax;
                    }
                    galTR[i]  = document.createElement('tr');
                    galTD0[i] = document.createElement('td');
                    galTD1[i] = document.createElement('td');
                    var node0 = document.createTextNode(year);
                    var node1 = document.createTextNode(allPhotos[gallery].title + ' (' +
                                                        allPhotos[gallery].photoArray.length + ')');
                    if (gallery == PhotoVars.currentAlbum) {
                        galTD0[i].className = "current year";
                        galTD1[i].className = "current";
                        var node1a = node1;
                    }
                    else {
                        galTD0[i].className = "year";
                        var node1a = document.createElement('a');
                        node1a.href = "javascript:myPhoto.loadGallery('" + gallery + "')";
                        node1a.appendChild(node1);
                        }
                    galTD0[i].appendChild(node0);
                    galTD1[i].appendChild(node1a);
                    galTR[i].appendChild(galTD0[i]);
                    galTR[i].appendChild(galTD1[i]);
                    galTBody.appendChild(galTR[i]);
                    i += 1;
                }
            }
        }        
        galTable.appendChild(galTBody);
        document.getElementById("MenuInnerBox").appendChild(galTable);
    },
    
    // Necessary for IE6:
    removeGalleryList: function() {
        numOldNodes = document.getElementById("MenuInnerBox").childNodes.length;
        for (n=0; n<numOldNodes; n++) {
            oldNode = document.getElementById("MenuInnerBox").childNodes[0];
            document.getElementById("MenuInnerBox").removeChild(oldNode);
        }
    },
    
    // Detect screen size and run Misc.setScreenSizeCss().
    // A small screen has a height of less than 1024 (e.g. < 1280x1024).
    autoSetScreenSizeCss: function() {
        var size = 'large';
        if (screen.height < 1024) { size = 'small'; };
        Misc.setScreenSizeCss(size);
    },
    
    // Add css classes to reduce margin size for small screens
    setScreenSizeCss: function(size) {
        if (size =='small') {
            myPhoto.sizeElems.each( function(elem) {
                Element.addClassName(elem, 'small');
                borderSize = 2*5;
            });
        }
        else {
            myPhoto.sizeElems.each( function(elem) {
                Element.removeClassName(elem, 'small');
                borderSize = borderSizeDefault;
            });
        }
    },

    // Handle a keystroke (prev, next, etc.)
    hitKey: function(e){ 
        if(window.event){ // IE
            var keyCode = e.keyCode;
        }
        else if(e.which){ // Netscape/Firefox/Opera
            var keyCode = e.which;
        }

        if (keyCode == 37) {
            var keyChar = "left arrow"; //not working
        }
        else if (keyCode == 39) {
            var keyChar = "right arrow"; //not working
        }
        else {
            var keyChar = String.fromCharCode(keyCode);
        }
        //alert(keyCode + ": " + keyChar);
        
        switch(keyChar){
            case "p":          return myPhoto.prevPhoto(); 
            case ">":          return myPhoto.prevPhoto(); 
            case ".":          return myPhoto.prevPhoto(); 
            case "left arrow": return myPhoto.prevPhoto(); 

            case "n":           return myPhoto.nextPhoto(); 
            case "<":           return myPhoto.nextPhoto(); 
            case ",":           return myPhoto.nextPhoto(); 
            case " ":           return myPhoto.nextPhoto(); 
            case "right arrow": return myPhoto.nextPhoto(); 

            case "g": return myPhoto.toggleGalMenu(); 
            
            // add cases for "h" (help), others(home?)
        }
    },
    
    // Remove duplicate values from an array
    uniqueArray: function( b ) {
        var a = [], i, l = b.length;
        for( i=0; i<l; i++ ) {
            if( a.indexOf(b[i], 0, b) < 0) { 
                a.push(b[i]); 
            }
        }
        return a;
    },
    
    // Returns true if str is an integer, and false otherwise
    isInt: function(str) {
    	var i = parseInt (str);
    	if (isNaN (i)) {
    		return false;
        } 
    	i = i . toString ();
    	if (i != str) {
    		return false;
        }
    	return true;
    },
    
    // Retruns true if a is an object, false otherwise
    isObject: function(a) {
        return (a && typeof a == 'object') || Misc.isFunction(a);
    },

    // Retruns true if a is a function, false otherwise
    isFunction: function(a) {
        return typeof a == 'function';
    }
   
};

/*--------------------------------------------------------------------------*/

// Additional methods 
Object.extend(Element, {
	getWidth: function(element) {
        element = $(element);
        return element.offsetWidth; 
	},
	setWidth: function(element,w) {
        element = $(element);
    	element.style.width = w +"px";
	},
	setHeight: function(element,h) {
        element = $(element);
    	element.style.height = h +"px";
	},
	setSrc: function(element,src) {
    	element = $(element);
    	element.src = src; 
	},
	setHref: function(element,href) {
    	element = $(element);
    	element.href = href; 
	},
	setInnerHTML: function(element,content) {
		element = $(element);
		element.innerHTML = content;
        /*
        // Remove previous list
        for (n=0; n<element.childNodes.length; n++) {
            element.removeChild(element.childNodes[0]);
        }
        newTextNode = document.createTextNode(content);
        element.appendChild(newTextNode);
        */
    },
    // IE doesn't like this function (?)
	setOpacity: function(element,content) {
        var percent_content = content*100;
		element = $(element);
		element.style.opacity = content;
		//element.style.-moz-opacity = content;
		element.style.filter = "alpha(opacity=" + percent_content + ")";
    }
});

/*--------------------------------------------------------------------------*/

var Slideshow = Class.create();

Slideshow.prototype = {
	initialize: function(photoId) {
		this.photoId    = photoId;
		this.photo      = 'Photo';
		this.photoCache = 'PhotoCache';
		this.photoBox   = 'Container';
		this.prevLink   = 'PrevLink';
		this.nextLink   = 'NextLink';
		this.photoInfo  = 'photoInfo';
		this.captionBox = 'CaptionBox';
		this.toggleMenu = 'toggleMenu';
		this.menuToggle	= $('toggleMenu');
		this.menuBox 	= $('MenuBox');
		this.caption    = 'Caption';
		this.counter    = 'Counter';
		this.gallery    = 'Gallery';
		this.copyright  = 'Copyrt';
		this.loader     = 'LoadBox';
		this.linkBox    = 'LinkBox';
        this.sizeElems  = ['Masthead', 'Container', 'photoInfo'];
	},
	getCurrentSize: function() {
		// Get current height and width, subtracting CSS border size
		this.wCur = Element.getWidth(this.photoBox)  - borderSize;
		this.hCur = Element.getHeight(this.photoBox) - borderSize;
	},
	getNewSize: function() {
		// Get current height and width
		this.wNew = PhotoVars.photoArray[this.photoId][1];
		this.hNew = PhotoVars.photoArray[this.photoId][2];
	},
	getScaleFactor: function() {
		this.getCurrentSize();
		this.getNewSize();
		// Scalars based on change from old to new
		this.xScale = (this.wNew / this.wCur) * 100;
		this.yScale = (this.hNew / this.hCur) * 100;
	},
	setNewPhotoParams: function() {
		// Set source of new image
		Element.setSrc(this.photo,PhotoVars.photoDir + PhotoVars.photoArray[this.photoId][0]);
		// Set anchor for bookmarking
        var currentAlbum   = PhotoVars.currentAlbum;
        var currentPhotoId = myPhoto.photoId;
        if (currentAlbum == PhotoVars.defaultAlbum) { 
            URLsuffix = "#" + (currentPhotoId + 1);
        }
        else { 
            URLsuffix = "#" + currentAlbum + "_" + (currentPhotoId + 1);
        }
		Element.setHref(this.prevLink, URLsuffix);
		Element.setHref(this.nextLink, URLsuffix);
	},
	setPhotoCaption: function() {
		// Add caption from gallery array
		Element.setInnerHTML(this.caption, PhotoVars.photoArray[this.photoId][3]);
		Element.setInnerHTML(this.counter, ((this.photoId+1) + '/' + PhotoVars.numPhotos));
		Element.setInnerHTML(this.gallery, PhotoVars.title);
		Element.setInnerHTML(this.copyright, 'Andrew Howard, ' + PhotoVars.photoArray[this.photoId][4]);
	},
	resizePhotoBox: function() {
		this.getScaleFactor();
		new Effect.Scale(this.photoBox, this.yScale, {scaleX: false, duration: 0.3, queue: 'front'});
		new Effect.Scale(this.photoBox, this.xScale, {scaleY: false, delay: 0.5, duration: 0.3});
		// Dynamically resize caption box as well
		Element.setWidth(this.photoInfo,this.wNew-(-borderSize));
    },
	showPhoto: function(){
		new Effect.Fade(this.loader, {delay: 0.5, duration: 0.3});
		// Workaround for problems calling object method "afterFinish"
		new Effect.Appear(this.photo, {duration: 0.5, queue: 'end', 
                                       afterFinish: function(){
                                            Element.show('CaptionBox');
                                            Element.show('toggleMenu');
                                            Element.show('PrevLink');
                                            Element.show('NextLink');
                                       }});
	},
    preloadNextImage: function() {
        // Figure out which image is next
        var photoIdCache = 0;
    	(this.photoId == (PhotoVars.photoArray.length - 1)) ? photoIdCache = 0 : photoIdCache = this.photoId + 1;
        var URL = PhotoVars.photoDir + PhotoVars.photoArray[photoIdCache][0];
        Element.setSrc(this.photoCache,URL);
    },
	nextPhoto: function(){
		// Figure out which photo is next
		(this.photoId == (PhotoVars.photoArray.length - 1)) ? this.photoId = 0 : this.photoId++;
		this.initSwap();
        // Google Analytics
        urchinTracker('/' + PhotoVars.currentAlbum + '_' + this.photoId);
	},
	prevPhoto: function(){
		// Figure out which photo is previous
		(this.photoId == 0) ? this.photoId = PhotoVars.photoArray.length - 1 : this.photoId--;
		this.initSwap();
        // Google Analytics
        urchinTracker('/' + PhotoVars.currentAlbum + '_' + this.photoId);
	},
    loadGallery: function(gallery){
        this.toggleGalMenu();
        this.photoId = 0;
        PhotoVars.setPhotoArray(gallery);
        this.initSwap();
        Misc.setHref();
        Misc.setPageTitle();
        // Google Analytics
        urchinTracker('/' + gallery);
    },
	toggleGalMenu: function() {
		// Show appropriate menu state when invoked
		if (menuViz == false) {
			menuViz = true;
            Element.hide(this.linkBox);
            Element.setOpacity(this.photo, 0.2);
			this.menuToggle.className = 'open';
			this.menuBox.className = 'open';
            Misc.generateGalleryList();
            //Effect.Appear('MenuBox');
		} else {
			menuViz = false;
            //Effect.Fade('MenuBox');
            Misc.removeGalleryList();
			this.menuToggle.className = '';
			this.menuBox.className = '';
            Element.setOpacity(this.photo, 0.999999999);
            Element.show(this.linkBox);
		}
        // remember to also set:
            //filter: alpha(opacity=80);
            //-moz-opacity: 0.8;
	},
	initSwap: function() {
        Misc.autoSetScreenSizeCss();
		// Begin by hiding main elements
		Element.show(this.loader);
		Element.hide(this.photo);
		Element.hide(this.captionBox);
		Element.hide(this.toggleMenu);
		Element.hide(this.prevLink);
		Element.hide(this.nextLink);
		// Set new dimensions and source, then resize
		this.setNewPhotoParams();
		this.resizePhotoBox();
		this.setPhotoCaption();
        // Preload next image
        this.preloadNextImage();
        //Misc.setHref();
	}
};

/*--------------------------------------------------------------------------*/

// Establish CSS-driven events via Behaviour script
var myrules = {
	'#Photo' : function(element){
		element.onload = function(){
			myPhoto.showPhoto();
		}
	},
	'#PrevLink' : function(element){
		element.onclick = function(){
			myPhoto.prevPhoto();
		}
	},
	'#NextLink' : function(element){
		element.onclick = function(){
			myPhoto.nextPhoto();
		}
	},
	'#toggleMenu' : function(element){
		element.onclick = function(){
			myPhoto.toggleGalMenu();
		}
	},
	a : function(element){
		element.onfocus = function(){
			this.blur();
		}
	}
};

// Add window.onload event to initialize
Behaviour.addLoadEvent(init);
Behaviour.apply();
var myPhoto = {};
function init() {
    Behaviour.register(myrules);
    //Misc.hitKey(event.keyCode);
    Misc.parseURL(document.location.href);
    PhotoVars.setPhotoArray(PhotoVars.currentAlbum);
	myPhoto = new Slideshow(PhotoVars.photoId);
	myPhoto.initSwap();
};
