function loadXMLDoc(dname) 
{
	var xmlDoc;
	if (window.XMLHttpRequest)
	{
  		xmlDoc=new window.XMLHttpRequest();
		xmlDoc.open("GET",dname,false);
  		xmlDoc.send("");
  		return xmlDoc.responseXML;
  	}
	// IE 5 and IE 6
	else if (ActiveXObject("Microsoft.XMLDOM"))
	{
  		xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
  		xmlDoc.async=false;
  		xmlDoc.load(dname);
  		return xmlDoc;
	}
	
	alert("Error loading document");
	return null;
}

// Loads the publications from an XML file
function loadPublications()
{
	// Global variables
	topicMap = new Object();
	
	topicMap.light = 0;
	topicMap.threed = 1;
	topicMap.projector = 2;
	topicMap.education = 3;
	topicMap.other = 4;
	
	topicMapDesc = new Array();
	topicMapDesc[topicMap.light] = "Visual appearance understanding and synthesis";
	topicMapDesc[topicMap.threed] = "3-D perception and robotics";
	topicMapDesc[topicMap.education] = "Education";
	topicMapDesc[topicMap.projector] = "Projector-based displays";
	topicMapDesc[topicMap.other] = "Other";

	xmlDoc = loadXMLDoc("pubs.xml");
	xmlPubs = xmlDoc.getElementsByTagName("pub");
	
	pubArray = new Array();
	
	for (var i=0; i < xmlPubs.length; i++) {
		type  = xmlPubs[i].getAttribute("type");
		year  = xmlPubs[i].getAttribute("year");
		isnew = xmlPubs[i].getAttribute("isnew");

		topic = topicMap[xmlPubs[i].getAttribute("topic")];

		title   = xmlPubs[i].getElementsByTagName("title")[0].childNodes[0].nodeValue;
		details = xmlPubs[i].getElementsByTagName("details")[0].childNodes[0].nodeValue;
		link    = xmlPubs[i].getElementsByTagName("link")[0].childNodes[0].nodeValue;
		thumb   = xmlPubs[i].getElementsByTagName("thumb")[0].childNodes[0].nodeValue;
		
		// load authors
		xmlAuthors = xmlPubs[i].getElementsByTagName("author");
		authors = new Array();
		for (j=0; j < xmlAuthors.length; j++) {
			authors.push(new Author(xmlAuthors[j].childNodes[0].nodeValue, xmlAuthors[j].getAttribute("link")));
		}
		pubArray.push(new Publication(title, authors, details, link, thumb, type, year, topic, isnew));
	}	
}

function setSortOption(sortOption)
{
	pubSortOption = sortOption;
}

// Displays the publications according to what the user wants
function displayPubs(tmpPubArray)
{
	pubsStr = "<h3> [ " + tmpPubArray[0].getSortTypeDesc() + " ] </h3>\n";
	
	pubsStr = pubsStr + "<div class=\"pub\"><table class=\"pub\">\n";
	for (var i=0; i < tmpPubArray.length; i++) {
		pubsStr = pubsStr + tmpPubArray[i].display();
	}
	pubsStr = pubsStr + "</table></div>\n";
	return pubsStr;
}

// Display publications by group, according to input sorting function
function displayPubsByGroup(sortOption) {
	pubSortOption = sortOption;

	// Sort
	var tmpPubArray = new Array();
	for (var i=0; i < pubArray.length; i++) {
		tmpPubArray.push(pubArray[i]);
	}
	tmpPubArray.sort(pubSort);
	
	// Split the publication list by the given group
 	var groupArray = new Array();

	// Create individual arrays
	var tmpArray = new Array(tmpPubArray[0]);
	var curVal = tmpPubArray[0].getSortType();
	
	for (var i=1; i < tmpPubArray.length; i++) {
		if (curVal != tmpPubArray[i].getSortType()) {
			// we found a new value. Save the old one and create a new publication group
			groupArray.push(tmpArray);
			
			tmpArray = new Array(tmpPubArray[i]);
			curVal = tmpPubArray[i].getSortType();
		} else {
			tmpArray.push(tmpPubArray[i]);
		}
	}
	// We're done, add the last one to the group array
	groupArray.push(tmpArray);
	
	// Now, iterate over the publication groups, and display them
	pubsStr = "";
	for (var i=0; i < groupArray.length; i++) {
		pubsStr = pubsStr + displayPubs(groupArray[i]);
	}
	pubsBlock = document.getElementById("testDiv");
	pubsBlock.innerHTML = pubsStr;
	
	// Cleanup
	delete tmpPubArray;
	for (var i=0; i < groupArray.length; i++) {
		delete groupArray[i];
	}
	delete groupArray;
}

// Define the publications class
function Publication(title, authors, details, link, thumb, type, year, topic, isnew)
{
	this.title = title;
	this.authors = authors; 
	this.details = details;
	this.link = link;
	this.thumb = thumb;
	this.type = type; 
	this.year = year;
	this.topic = topic;
	this.isnew = isnew;
}

// Access
Publication.prototype.getYear = function() {return this.year;}
Publication.prototype.getType = function() {return this.type;}
Publication.prototype.getTopic = function() {return this.topic;}
Publication.prototype.isNew = function() {return this.isnew == "1";}

Publication.prototype.getSortTypeDesc = function() 
{
	switch(pubSortOption) {
		// type
		case 0: return this.getType();
		// year
		case 1: return this.getYear();
		// topic
		case 2: return topicMapDesc[this.getTopic()]; 
		// default
		default: return null;
	}
}

Publication.prototype.getSortType = function() 
{
	switch(pubSortOption) {
		// type
		case 0: return this.getType();
		// year
		case 1: return this.getYear();
		// topic
		case 2: return this.getTopic(); 
		// default
		default: return null;
	}
}

function pubSort(pub1, pub2) {
	switch(pubSortOption) {
		// type
		case 0: return pubSortByType(pub1, pub2);
		// year
		case 1: return pubSortByYear(pub1, pub2);
		// topic
		case 2: return pubSortByTopic(pub1, pub2); 
	}
}
function pubSortByType(pub1, pub2) {return pub1.type-pub2.type;}
function pubSortByYear(pub1, pub2) {return pub2.year-pub1.year;}
function pubSortByTopic(pub1, pub2) {return pub1.topic-pub2.topic;}

// Member function: display the current publication
Publication.prototype.display = function() 
{
	pubStr = "<tr><td> <a href=\"" + this.link + "\">";
	pubStr = pubStr+"<img class=\"pub\" src=\"" + this.thumb + "\" width=\"100\" alt=\"Icon\" /></a></td>\n";
	pubStr = pubStr+"<td>";
	if (this.isNew()) {
		pubStr = pubStr+"<img class=\"new\" src=\"images/new-thumb.png\" width=\"50\" alt=\"new\" />";
	}
	pubStr = pubStr+"<a href=\"" + this.link + "\">" + this.title + "</a><br />\n";
	
	// Display authors
	pubStr = pubStr + this.authors[0].display();
	switch(this.authors.length) {
		case 1: break;
		case 2: pubStr = pubStr + " and " + this.authors[1].display(); break;
		default: 
			for (var i=1; i < this.authors.length-1; i++) {
				pubStr = pubStr + ", " + this.authors[i].display();
			} 
			pubStr = pubStr + ", and " + this.authors[this.authors.length-1].display();
	}
	pubStr = pubStr + "<br/>\n";
	pubStr = pubStr + this.details + "\n";
	pubStr = pubStr + "</td></tr>\n";
	
	return pubStr;
}

// Define the authors class
function Author(name, link) 
{
	this.name = name;
	this.link = link;
}

Author.prototype.hasLink = function() {return this.link != null;}

// Display a single author (with or without link)
Author.prototype.display = function() 
{
	authStr = "";
	if (this.hasLink()) {
		authStr = authStr + "<a href=\"" + this.link + "\">";
	}
	authStr = authStr + this.name;
	if (this.hasLink()) {
		authStr = authStr + "</a>";
	}
	return authStr;
}
