//variable that stores information about current request (by date, by gallery, or by tag)
var currentRequest;

//defines number of images per page
var IMG_PER_PG = 8;

addOnload(initAll);

//function that handles multiple functions for the window.onload event
function addOnload(newFunction) {

	//get current onload function
	var oldOnload = window.onload;
	
	if(typeof oldOnload == "function") {
		
		//run both the old function and the new function when page loads
		window.onload = function() {
			if(oldOnload) {
				oldOnload();
			}
			newFunction();
		}
	} else {
		//run the new funciton
		window.onload = newFunction;
	}
}

//function that makes the xmlhttp request
function initAll() {

	document.getElementById("menuselect").onchange = photoSwitch;

	if (window.XMLHttpRequest) { //Normal browsers
		xmlh = new XMLHttpRequest();
	} else {
		if (window.ActiveXObject) { //#$%^%#$% Internet Explorer....
			try {
				xmlh = new ActiveXObject("Microsoft.XMLHTTP");
			}
			catch (e) {}
		}
	}
		
	if (xmlh) { //if the request was succcessful, get the info and populate the table, else do nothing
		getPhotosByDate();
	}
	
}

function photoSwitch() {

	switch(document.getElementById("menuselect").selectedIndex) {
		case 0:
		case 1:
			getPhotosByDate();
			break;
		default:
			getPhotosByGallery();
			break;
	}
	
}
		

//function that defines the request object; takes mysql SELECT, FROM, and WHERE statements as arguments
function request(SELECT, FROM, WHERE) {

	//starting page number (0 by default)
	this.pageStart = 0;
	
	//total number of images that match the mysql conditions (is set by the getNumImages() method)
	this.numImages = -1;
	
	//mysql query items
	this.SELECT = SELECT;
	this.FROM = FROM;
	this.WHERE = WHERE;
	this.LIMIT = '0, ' + IMG_PER_PG;
	
	//define methods
	this.getNumImages = getNumImages;
	this.getNumPages = getNumPages;
	this.getImagesDisplayed = getImagesDisplayed;
	this.setLimit = setLimit;

}
	
//method of request() that gets the total number of images that match the request
function getNumImages() {

	//if the number has laready been set; don't recalculate
	if(this.numImages >= 0) {
		return this.numImages;
	}
	
	//request xml data synchronously
	xmlh.open("POST", '/scripts/get_num_photos.php', false);
	
	//create post data
	var post_data = 'from=' + this.FROM + '&where=' + this.WHERE;
	
	//Send the proper header information along with the request
	xmlh.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	xmlh.setRequestHeader("Content-length", post_data.length);
	xmlh.setRequestHeader("Connection", "close");
	
	//send post data
	xmlh.send(post_data);
	
	if(xmlh.readyState == 4) { //only run after the data is fully loaded
		if(xmlh.status == 200) { //make sure the file is present
		
			//set the number of images to the request object
			this.numImages = Number(xmlh.responseText);
			
			//return the number of images
			return this.numImages;
		}
	}

}

//method of request() that calculates the number of pages nevessary to display all of the 
function getNumPages() {

	//if the numImages attribute hasn't been set, then set it
	if(this.numImages < 0) {
		this.getNumImages();
	}
	
	//return total number of images/images per page, rounded up to the next whole number
	return Math.ceil(this.numImages/IMG_PER_PG);
	
}

//method of request() that determines which images in the set are being displayed, and returns a string (e.g. '1-8')
function getImagesDisplayed() {

	//if the numImages attribute hasn't been set, then set it
	if(this.numImages < 0) {
		this.getNumImages();
	}
	
	//test for an empty set (should never happen, but who knows?), print either 0 or pageStart*IMG_PER_PG +1
	var imagesDisplayed = (this.numImages>0)?((this.pageStart*IMG_PER_PG)+1):0;
	
	//add a dash
	imagesDisplayed += '-';
	
	//either print the previous number + 8 or the total number of images (if we're at the end of a list)
	imagesDisplayed += (((this.pageStart*IMG_PER_PG)+IMG_PER_PG)<this.numImages)?((this.pageStart*IMG_PER_PG)+IMG_PER_PG):this.numImages;
	
	//return the string that was built
	return imagesDisplayed;
	
}

function setLimit() {
	this.LIMIT = this.pageStart*IMG_PER_PG + ', ' + IMG_PER_PG;
}

//function that runs the get_photos.php script with arbitrary arguments. It takes 5 strings as arguments: the first four contain the text for the corresponding parts of a mysql query; the last is a function that will be assigned to the onreadystatechange event handler.
function makeXMLRequest(SELECT, FROM, WHERE, LIMIT, functionName) {

	//request xml data asynchronously
	xmlh.open("POST", '/scripts/get_photos.php', true);
	
	//when data is loaded, run the function that displays the image table
	xmlh.onreadystatechange = functionName;
	
	//create post data
	var post_data = 'select=' + SELECT + '&from=' + FROM + '&where=' + WHERE + '&limit=' + LIMIT;
	
	//Send the proper header information along with the request
	xmlh.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	xmlh.setRequestHeader("Content-length", post_data.length);
	xmlh.setRequestHeader("Connection", "close");
	
	//send post data
	xmlh.send(post_data);
	
}

//function that retrieves information about a single photo from the database
function getPhoto() {

	//set mysql query statements
	var SELECT = '*';
	var FROM = 'photos, galleries';
	var WHERE = 'photos.id=' + this.id + ' AND gallery=galleries.id';
	var LIMIT = '0, 1';
	
	//request the data from the server
	makeXMLRequest(SELECT, FROM, WHERE, LIMIT, showImage);

}

//Retrieves all photos from database ordered by date
function getPhotosByDate() {
	
	//hide the content div
	document.getElementById("imagepage").style.visibility = "hidden";

	//set mysql query statements
	var SELECT = 'photos.id, gallery, filename, filetype, title, date, uploaded_by, gallery_name';
	var FROM = 'photos, galleries';
	var WHERE = 'gallery=galleries.id';
	
	//start a new request
	currentRequest = false;
	currentRequest = new request(SELECT, FROM, WHERE);
		
	//set the subheading
	var subheading = 'Photos ' + currentRequest.getImagesDisplayed();
	subheading += ' of ' + currentRequest.getNumImages();
	subheading += '.';
	document.getElementById("displayingphotos").innerHTML = subheading;
	
	//set the photo page title
	document.getElementById("photopagetitle").innerHTML = 'Showing All Photos by Date';
	
	//request the data from the server
	makeXMLRequest(currentRequest.SELECT, currentRequest.FROM, currentRequest.WHERE, currentRequest.LIMIT, showImageTable);

	
}

//function that retrieves all photos from a given gallery from database
function getPhotosByGallery() {
	
	//hide the content div
	document.getElementById("imagepage").style.visibility = "hidden";
	
	var indexId = document.getElementById("menuselect").selectedIndex;
	
	var galleryId = (indexId>0)?indexId-1:this.id;

	//set mysql query statements
	var SELECT = 'photos.id, gallery, filename, filetype, title, date, uploaded_by, gallery_name';
	var FROM = 'photos, galleries';
	var WHERE = 'gallery = ' + galleryId + ' AND gallery=galleries.id';
	
	//start a new request
	currentRequest = false;
	currentRequest = new request(SELECT, FROM, WHERE);
	
	//set the subheading
	var subheading = 'Photos ' + currentRequest.getImagesDisplayed();
	subheading += ' of ' + currentRequest.getNumImages();
	subheading += '.';
	document.getElementById("displayingphotos").innerHTML = subheading;
	
	//request the data from the server
	makeXMLRequest(currentRequest.SELECT, currentRequest.FROM, currentRequest.WHERE, currentRequest.LIMIT, showImageTable);
	
	//set the photo page title
	if(indexId>0) {
		document.getElementById("photopagetitle").innerHTML = 'Showing Photos from Gallery: ' + document.getElementById("menuselect").options[indexId].value;
	} else {
		document.getElementById("photopagetitle").innerHTML = 'Showing Photos from ' + this.innerHTML.substr(4);
	}
	
}

//function that retrieves all photos with a given tag from database
function getPhotosByTag() {
	
	//hide the content div
	document.getElementById("imagepage").style.visibility = "hidden";

	//set mysql query statements
	var SELECT = 'photos.id, gallery, filename, filetype, title, date, uploaded_by, gallery_name';
	var FROM = 'photos, galleries';
	var WHERE = "tags LIKE  '%" + this.id + "%' AND gallery=galleries.id";
		
	//start a new request
	currentRequest = false;
	currentRequest = new request(SELECT, FROM, WHERE);
	
	//set the subheading
	var subheading = 'Photos ' + currentRequest.getImagesDisplayed();
	subheading += ' of ' + currentRequest.getNumImages();
	subheading += '.';
	document.getElementById("displayingphotos").innerHTML = subheading;
	
	//request the data from the server
	makeXMLRequest(currentRequest.SELECT, currentRequest.FROM, currentRequest.WHERE, currentRequest.LIMIT, showImageTable);
	
	//set the photo page title
	document.getElementById("photopagetitle").innerHTML = 'Showing Photos with Tag: ' + this.id;
	
}

//function that retireves photos based on page numbers (i.e. currentRequest does not need to be reset)
function getPhotosByPage() {
	
	//hide the content div
	document.getElementById("imagepage").style.visibility = "hidden";
	
	//set the subheading
	var subheading = 'Photos ' + currentRequest.getImagesDisplayed();
	subheading += ' of ' + currentRequest.getNumImages();
	subheading += '.';
	document.getElementById("displayingphotos").innerHTML = subheading;
	
	//request the data from the server
	makeXMLRequest(currentRequest.SELECT, currentRequest.FROM, currentRequest.WHERE, currentRequest.LIMIT, showImageTable);

}
	
//function that adds content to the table of images
function showImageTable() {

	//declare loop index
	var i = 0;
	
	//reset selectedindex of form
	document.getElementById("menuselect").selectedIndex = 0;
	
	if(xmlh.readyState == 4) { //only run after the data is fully loaded
		if(xmlh.status == 200) { //make sure the file is present
		
			//clear table
			clearTable();
			
			//show content div
			document.getElementById("imagepage").style.visibility = "visible";
			
			//make sure photo display div is off!
			hideImage();
			
			//loop through the returned XML photo by photo if a result is obtained
			if(currentRequest.numImages > 0) {
				for(i=0;i<xmlh.responseXML.documentElement.getElementsByTagName("photo").length;i++) {
	
					//set the id used to identify the table cell we want to work with
					//var id = "photo" + i;
					var titleCell = document.getElementById("title"+i);
					var photoCell = document.getElementById("photo"+i);
					var infoCell = document.getElementById("info"+i);
					
					//start adding content to the cell
					var xml = xmlh.responseXML.documentElement;
					
					//start with title; get the title span and append it to the cell
					var photoTitle = addTitle(xml.getElementsByTagName("title")[i].childNodes[0].nodeValue);
					titleCell.appendChild(photoTitle);
					
					//now the image
					var image = addImage('thumb_' + xml.getElementsByTagName("filename")[i].childNodes[0].nodeValue, xml.getElementsByTagName("filetype")[i].childNodes[0].nodeValue, xml.getElementsByTagName("title")[i].childNodes[0].nodeValue);
					image.id = xml.getElementsByTagName("id")[i].childNodes[0].nodeValue; //add photo id number
					photoCell.appendChild(image);
					
					//now the gallery
					var gallery = addGallery(xml.getElementsByTagName("gallery")[i].childNodes[0].nodeValue, xml.getElementsByTagName("gallery_name")[i].childNodes[0].nodeValue);
					infoCell.appendChild(gallery);
					
					//finally the upload info
					var uploadInfo = addUploadInfo(xml.getElementsByTagName("date")[i].childNodes[0].nodeValue, xml.getElementsByTagName("uploaded_by")[i].childNodes[0].nodeValue);
					infoCell.appendChild(uploadInfo);
					
		
				}
			
			}
			
			//print the page "links" at the bottom of the page
			printPages();
			
			
		}
	}
}

//function that pops up the div containing information about one particular image
function showImage() {

	if(xmlh.readyState == 4) { //only run after the data is fully loaded
		if(xmlh.status == 200) { //make sure the file is present
			
			//show the image window and set the callback function for the close button
			document.getElementById("showphoto").style.display = "block";
			document.getElementById("closebutton").onclick = hideImage;
			
			//start populating the image window
			var activeDiv = document.getElementById("photodisplaytitle");
			xml = xmlh.responseXML.documentElement;
			
			//title
			var photoTitle = addTitle(xml.getElementsByTagName("title")[0].childNodes[0].nodeValue);
			activeDiv.appendChild(photoTitle);
			
			//switch to photodisplay box
			activeDiv = document.getElementById("photodisplay");
			
			//photo... start by creating the link
			var linkObject = addLink('/images/galleries/' + xml.getElementsByTagName("filename")[0].childNodes[0].nodeValue + '.' + xml.getElementsByTagName("filetype")[0].childNodes[0].nodeValue);
			
			//now create the image
			var image = addImage('preview_' + xml.getElementsByTagName("filename")[0].childNodes[0].nodeValue, xml.getElementsByTagName("filetype")[0].childNodes[0].nodeValue, xml.getElementsByTagName("title")[0].childNodes[0].nodeValue);
			linkObject.appendChild(image);
			
			//add the link to the div
			activeDiv.appendChild(linkObject);
			
			//add the caption
			var caption = addCaption(xml.getElementsByTagName("caption")[0].childNodes[0].nodeValue);
			activeDiv.appendChild(caption);
			
			//add the metainfo and gallery link
			activeDiv = document.getElementById("metainfo");
			var gallery = addGallery(xml.getElementsByTagName("gallery")[0].childNodes[0].nodeValue, xml.getElementsByTagName("gallery_name")[0].childNodes[0].nodeValue);
			activeDiv.appendChild(gallery);
			
			//finally the upload info
			var uploadInfo = addUploadInfo(xml.getElementsByTagName("date")[0].childNodes[0].nodeValue, xml.getElementsByTagName("uploaded_by")[0].childNodes[0].nodeValue);
			activeDiv.appendChild(uploadInfo);
				
			//add the tags
			activeDiv = document.getElementById("tagsdisplay");
			var tags = addTags(xml.getElementsByTagName("tags")[0].childNodes[0].nodeValue);
			activeDiv.appendChild(tags);
		
		
		}
	}
}

//function that hides/clears the image display div
function hideImage() {

	//hide the image div
	document.getElementById("showphoto").style.display = "none";
	
	var j;
	
	//make an array of all elements to be cleared
	var div = new Array();
	div[0] = document.getElementById("photodisplaytitle");
	div[1] = document.getElementById("photodisplay");
	div[2] = document.getElementById("metainfo");
	div[3] = document.getElementById("tagsdisplay");
	
	//for each element in the array, clear out all child nodes
	for (j in div) {
		while(div[j].hasChildNodes()) {
			div[j].removeChild(div[j].firstChild);
		}
	}
	
}

//function that clears out the table
function clearTable() {
	
	var i;
	
	for(i=0;i<IMG_PER_PG;i++) {
		var cell = document.getElementById("title"+i);
		while(cell.hasChildNodes()) {
			cell.removeChild(cell.firstChild);
		}
		var cell = document.getElementById("photo"+i);
		while(cell.hasChildNodes()) {
			cell.removeChild(cell.firstChild);
		}
		var cell = document.getElementById("info"+i);
		while(cell.hasChildNodes()) {
			cell.removeChild(cell.firstChild);
		}
	}
	
}
	
//function that gnerates photo title. Takes the title string as an argument, and returns a span containing the text
function addTitle(titletext) {
	
	//create a new span of class phototitle
	var newTitle = document.createElement("span");
	newTitle.className = "phototitle";
	
	//put the title's text inside the span
	newTitle.innerHTML = titletext + "<br />";
	
	//return the span object
	return newTitle;
}
	
//function that generates image for table. Takes 3 strings as arguments: filename, filetype, and alternate text
function addImage(imageFileName, imageFileType, imageAltText) {

	//create a new image
	var newImage = document.createElement("img");
	
	//append the src and alt attributes
	newImage.src = '/images/galleries/' + imageFileName + '.' + imageFileType;
	newImage.alt = imageAltText;
	
	//set the onclick behavior
	newImage.onclick = getPhoto;
	
	//return the image object
	return newImage;
	
}

//function that generates a gallery name for the table; takes an integer gallery number (for the database) and a string gallery name
function addGallery(galleryNum, galleryName) {

	//create a span for the gallery
	var newGallery = document.createElement("span");
	
	newGallery.className = "photogallerytext";
	newGallery.innerHTML = 'Gallery: ' + galleryName;
	newGallery.id = galleryNum;
	newGallery.onclick = getPhotosByGallery;
	
	//return the gallery object
	return newGallery;
	
}

//function that generates the upload date and person name; takes a date and name
function addUploadInfo(date, person) {

	//create a new span for this info
	var newUploadInfo = document.createElement("span");
	
	//set class name and content
	newUploadInfo.className = "photouploadinfo";
	newUploadInfo.innerHTML = "Uploaded " + date + " by " + person;
	
	//return uploadinfo object
	return newUploadInfo;
	
}

//function that creates a link object; takes a url string as an argument. For now, hard-coding target="_blank"
function addLink(url) {

	//create a new anchor tag
	var newLink = document.createElement("a");
	
	//add url and target
	newLink.href = url;
	newLink.target = "_blank";
	
	//return link object
	return newLink;
	
}

//function that creates the object containing a photo caption; takes a caption string as an argument
function addCaption(caption) {

	//create a paragraph
	var newCaption = document.createElement("p");
	
	//add the text
	newCaption.innerHTML = caption;
	
	//return the object
	return newCaption;
	
}

//function that generates the object containing the tags for a photo; takes a string of ", " separated tags as an argument
function addTags(tags) {

	var i;
	var newTag;
	
	//make the paragraph
	var newTagParagraph = document.createElement("p");
	
	//add the title "Tags"
	newTagParagraph.innerHTML = '<span style="font-size:12pt;font-weight:bold;line-height:70%;text-decoration:underline">Tags<br /><br /></span>';
	
	//make an array of the tags, breaking at every instance of ", "
	var newstr = tags.split(", ");
	
	//append each tag as a span with class "tag", id of the tag text, and onclick handler
	for (i in newstr) {
		newTag = document.createElement("span");
		newTag.className = "tag";
		newTag.id = newstr[i];
		newTag.innerHTML = newstr[i] + "<br />";
		newTag.onclick = getPhotosByTag;
		newTagParagraph.appendChild(newTag);
	}
	
	//return the paragraph object
	return newTagParagraph;
	
}

//function that creates the pagination "links" at the bottom of the page
//Note: the pageStart begins counting from 0; but the page numbering begins at 1!
function printPages() {

	//get total number of pages and current page
	var numPages = currentRequest.getNumPages();
	var currentPage = currentRequest.pageStart;
	
	//declare variable to hold text for innerHTML
	var pageString = '';
	
	//loop index
	var i;
	
	//find out where we are with respect to the total number of pages
	switch (numPages-currentPage) {
		//first page; don't make a "previous" button
		case numPages:
			for(i=1;i<=numPages;i++) {
				if (i == (currentPage+1)) {
					pageString += i + '&nbsp;';
				} else {
					pageString += '<span onclick=setPage(' + (i-1) + ') class="pagelink">' + i + '</span>&nbsp;';
				}
			}
			pageString += '<span onclick="incPage()" class="pagelink">Next&gt;</span>';
			break;
		//last page; don't make a "Next" button (numPages >= 1 , but currentPage >= 0, so currentPage <= numPages-1)
		case 1:
			pageString += '<span onclick="decPage()" class="pagelink">&lt;Previous</span>&nbsp;';
			for(i=1;i<=numPages;i++) {
				if (i == (currentPage+1)) {
					pageString += i + '&nbsp;';
				} else {
					pageString += '<span onclick=setPage(' + (i-1) + ') class="pagelink">' + i + '</span>&nbsp;';
				}
			}
			break;
		//somewhere in between; make both "previous" and "next" buttons
		default:
			pageString += '<span onclick="decPage()" class="pagelink">&lt;Previous</span>&nbsp;';
			for(i=1;i<=numPages;i++) {
				if (i == (currentPage+1)) {
					pageString += i + '&nbsp;';
				} else {
					pageString += '<span onclick=setPage(' + (i-1) + ') class="pagelink">' + i + '</span>&nbsp;';
				}
			}
			pageString += '<span onclick="incPage()" class="pagelink">Next&gt;</span>';
			break;
	}
	
	
	if(numPages == 0 || numPages == 1) {
		pageString = '';
	}
	
	document.getElementById("pageselect").innerHTML = pageString;
	
}

//function that selects a page
function setPage(i) {
	
	currentRequest.pageStart = i;
	currentRequest.setLimit();
	getPhotosByPage();

	
}

//function that increments the page
function incPage() {

	currentRequest.pageStart++;
	currentRequest.setLimit();
	getPhotosByPage();
	
}

//function that decrements the page
function decPage() {

	currentRequest.pageStart--;
	currentRequest.setLimit();
	getPhotosByPage();
		
}