/**
 * Small helper library
 */
var Lib = function() {};
Lib.prototype = {
	/**
	 * PrototypeJS style 'get element by id'
	 */
	$: function (elementId) {
		return document.getElementById(elementId);
	},

	/**
	 * Add a class
	 */
	addClass: function (element, add) {
		if (element.className && element.className.length) {
			element.className = element.className+' '+add;
		} else {
			element.className = add;
		}
	},

	/**
	 * Remove a class
	 */
	removeClass: function (element, remove) {
		element.className = null;
	},

	/** Attach events **/
	addEvent: function (obj, type, fn) {
		if (obj.addEventListener) {
			obj.addEventListener( type, fn, false );
		}
		else if (obj.attachEvent) {
			obj["e"+type+fn] = fn;
			obj[type+fn] = function() { obj["e"+type+fn]( window.event ); };
			obj.attachEvent( "on"+type, obj[type+fn] );
		}
		else {
			obj["on"+type] = obj["e"+type+fn];
		}
	},

	/** Get an object for making an (X)ml (H)TTP (R)equest **/
	createXhr: function () {
		var methods = [
			function() { return new XMLHttpRequest(); },
			function() { return new ActiveXObject('Msxml2.XMLHTTP'); },
			function() { return new ActiveXObject('Microsoft.XMLHTTP'); }
		];
		
		for(var i = 0, len = methods.length; i < len; i++) {
			try {
				methods[i]();
			}
			catch(e) {
				continue;
			}
			this.createXhr = methods[i];
			return methods[i]();
		}
		throw new Error('No XHR/AJAX support');
	},

	/** Make an XHR call **/
	xhRequest: function(method, url, callback, postVars) {
		method = method.toUpperCase();
		var xhr = this.createXhr();
		xhr.onreadystatechange = function() {
			if (xhr.readyState == 4) {
				callback(xhr);
			} else return;
		};
		xhr.open(method, url, true);
		if(method !== 'POST') postVars = null;
		xhr.send(postVars);
	},

	/**
	 * Find elements by class name
	 */
	getElementsByClassName: function getElementsByClassName(classname, node)  {
	    if(!node) node = document.getElementsByTagName("body")[0];
	    var a = [];
	    var re = new RegExp('\\b' + classname + '\\b');
	    var els = node.getElementsByTagName("*");
	    for(var i=0,j=els.length; i<j; i++) {
	        if(re.test(els[i].className))a.push(els[i]);
		}
	    return a;
	}

};

/**
 * Prototype-like bind function for scoping
 */
Function.prototype.bind = function(){ 
	var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift(); 
	return function(){ 
		return fn.apply(object, args.concat(Array.prototype.slice.call(arguments))); 
	}; 
};

/**
 * Trim a string 
 */
String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); }

/**
 * create an instance of our Lib to use
 */
var lib = new Lib();

/**
 * This class handles the highlighting of book icons on the main page
 */
var BookCoverActivator = function () {
	this.baseClass = 'kbsBook';
	this.activeImageClass = 'kbsBookOn';
	this.activeLinkClass = 'kbsOn';
	this.baseImageClass = 'kbsBookOff';
	this.attach();
};
BookCoverActivator.prototype = {
	clearAll: function () {
		var thisLink = lib.getElementsByClassName(this.activeLinkClass)[0];
		lib.removeClass(thisLink, this.activeLinkClass);

		var thisImage = lib.getElementsByClassName(this.activeImageClass)[0];
		lib.removeClass(thisImage, this.activeImageClass);
		lib.addClass(thisImage, this.baseImageClass);
	},

	clickHandler: function (element) {
		this.clearAll();
		if (element.parentNode.className == this.baseClass) {
			var theParent = element.parentNode;
		} else if (element.parentNode.parentNode.className == this.baseClass) {
			var theParent = element.parentNode.parentNode;
		} else {throw('Cant find the parent element!');}
		
		var theImage = theParent.getElementsByTagName('img')[0];
		var theLink = theParent.getElementsByTagName('a')[1];
		lib.removeClass(theImage, this.baseImageClass);
		lib.addClass(theImage, this.activeImageClass);
		lib.addClass(theLink, this.activeLinkClass);
	},

	attach: function () {
		var all = lib.getElementsByClassName(this.baseClass);
		for (var i=0;i<all.length;i++) {
			var theseLinks = all[i].getElementsByTagName('a');
			for (var g=0;g<theseLinks.length;g++) {
				var thisLink = theseLinks[g];
				lib.addEvent(thisLink, 'click', this.clickHandler.bind(this, thisLink));
				thisLink.onclick = function () {return true;};
			}
		}
	}
};

/** container classes **/
function Setting(settingNode) {
	this.name = settingNode.getElementsByTagName('settingname')[0].firstChild.nodeValue.trim();
	this.desc = settingNode.getElementsByTagName('settingdescription')[0].firstChild.nodeValue.trim();
};

Setting.prototype = {
	getName: function () {
		return this.name;
	},
	
	getDesc: function () {
		return this.desc;
	}
};

function Character(charNode) {
	this.name = charNode.getElementsByTagName('name')[0].firstChild.nodeValue.trim();
	this.bio = charNode.getElementsByTagName('bio')[0].firstChild.nodeValue.trim();
};

Character.prototype = {
	getName: function () {
		return this.name;
	},
	
	getBio: function () {
		return this.bio;
	}
};

function CharacterCollection() {
	this.main = Array();
	this.secondary = Array();
	this.mainTitle = 'MAIN CHARACTERS';
	this.secondaryTitle = 'SECONDARY CHARACTERS';
};

CharacterCollection.prototype = {
	addMain: function (charObj) {
		this.main.push(charObj);
	},
	
	addSecondary: function (charObj) {
		this.secondary.push(charObj);
	},
	
	getMain: function () {
		return this.main;
	},
	
	getSecondary: function () {
		return this.secondary;
	},
	
	setMainTitle: function (mTitle) {
		this.mainTitle = mTitle;
	},
	
	setSecondaryTitle: function (sTitle) {
		this.secondaryTitle = sTitle;
	},
	
	getMainTitle: function () {
		return this.mainTitle;
	},
	
	getSecondaryTitle: function () {
		return this.secondaryTitle;
	}
}

/**
 * Scholastic MiniSite XML parsing widget
 */
function MiniSite(currentPage, xmlUrl) {
	this.currentPage = currentPage;
	this.xmlFile(xmlUrl);
	
	if (window.location.hash) {
		if (window.location.hash.indexOf('#') === false) 
		{ this.defaultBook = window.location.hash;}
		else
		{ this.defaultBook = window.location.hash.substring(1);}
	} else {
		this.defaultBook = 1;
	}
};

MiniSite.prototype = {
	xmlFile: function (xmlFile) {
		this.xmlFile = xmlFile;
		lib.xhRequest('get', xmlFile, 
			this.xmlReady.bind(this)
		);
	},

	xmlReady: function (transport) {
		this.xml = transport.responseXML;
		this.books = this.xml.getElementsByTagName('book');
		this.titles = Array();
		for (var i = 0;i<this.books.length;i++) {
			this.titles[i] = this.books[i].getElementsByTagName('title')[0].firstChild.nodeValue.trim();
		}		
		this.buildCurrentPage();
	},
	
	buildCurrentPage: function () {
		switch (this.currentPage) {
			case 'plots':
				this.doPlots();
				this.buildSelector('kbsPlotPull');
			break;
			
			case 'characters':
				this.doCharacters();
				this.buildSelector('kbsPlotPull');
			break;
			
			case 'settings':
				this.doSettings();
				this.buildSelector('kbsPlotPull');
			break;
			
			default:
				return;
		}
	},
	
	buildSelector: function (selectId) {
		var selector = lib.$(selectId);
		for (var i =0;i<this.titles.length;i++) {
			if (i+1 == this.defaultBook) {var isDefault = true;} else {var isDefault = false;}
			selector.options[selector.options.length] = new Option('#'+(i+1)+" "+this.titles[i], (i+1),isDefault,isDefault);
		}
		//selector.value = this.defaultBook;
		lib.addEvent(selector,'change',this.selectChangeHandler.bind(this, selector));
	},
	
	selectChangeHandler: function (selector) {
		switch (this.currentPage) {
			case 'plots':
				this.showPlot(selector.value);
			break;
			
			case 'settings':
				this.showSettings(selector.value);
			break;
			
			case 'characters':
				this.showCharacters(selector.value);
			break;
		}
	},
	
	doPlots: function () {		
		this.plots = Array();
		this.releaseDates = Array();
		for (var i = 0;i<this.books.length;i++) {
			this.plots[i] = this.books[i].getElementsByTagName('summary')[0].firstChild.nodeValue.trim();
			this.releaseDates[i] = this.books[i].getElementsByTagName('releasedate')[0].firstChild.nodeValue.trim();
		}
		this.showPlot(this.defaultBook);
	},

	showPlot: function (plotNumber) {
		if (!plotNumber) { var plotNumber = 1; };
		plotNumber = plotNumber-1;
		
		var plotContainer = lib.getElementsByClassName('kbsMainTxt')[0];
		plotContainer.innerHTML = '';
		
		var heading = document.createElement('h2');
		heading.appendChild(document.createTextNode(this.titles[plotNumber]));
		plotContainer.appendChild(heading);
		
		var plot = document.createElement('p');
		plot.innerHTML = this.plots[plotNumber];
		plotContainer.appendChild(plot);
		
		var release = document.createElement('p');
		release.className = 'kbsRelease';
		release.appendChild(document.createTextNode('Release Date: '+this.releaseDates[plotNumber]));
		plotContainer.appendChild(release);
	},
	
	doSettings: function () {
		this.settings = Array();
		for (var i = 0;i<this.books.length;i++) {
			this.settings[i] = Array();
			var settings = this.books[i].getElementsByTagName('setting');
			for (var z=0;z<settings.length;z++) {
				this.settings[i][z] = new Setting(settings[z]);
			}
		}
		
		this.showSettings(this.defaultBook);
	},
	
	showSettings: function (bookNum) {
		if (!bookNum) {var bookNum = 1;}
		bookNum = bookNum-1;
		
		var settingsContainer = lib.$('kbsSettingsContainer');
		settingsContainer.innerHTML = '';
		
		var heading = document.createElement('h2');
		heading.appendChild(document.createTextNode(this.titles[bookNum]));
		settingsContainer.appendChild(heading);
				
		for (var i=0;i<this.settings[bookNum].length;i++) {
			
			var setHead = document.createElement('p');
			setHead.className = 'kbsSettingTxt';
			setHead.innerHTML = this.settings[bookNum][i].getName();
			settingsContainer.appendChild(setHead);
			
			var setBody = document.createElement('p');
			setBody.className = 'kbsMainSettingTxt';
			setBody.innerHTML = this.settings[bookNum][i].getDesc();
			settingsContainer.appendChild(setBody);
		}
	},

	doCharacters: function () {
		this.characters = Array();
		for (var i=0;i<this.books.length;i++) {
			this.characters[i] = new CharacterCollection();
			var mainTag = this.books[i].getElementsByTagName('maincharacters')[0];
			if (mainTag.getAttribute('title')) {
				this.characters[i].setMainTitle(mainTag.getAttribute('title'));
			}
			
			var secondaryTag = this.books[i].getElementsByTagName('secondarycharacters')[0];
			if (secondaryTag.getAttribute('title')) {
				this.characters[i].setSecondaryTitle(secondaryTag.getAttribute('title'));	
			}
			
			var mains = mainTag.getElementsByTagName('character');
			for (var z = 0;z<mains.length;z++) {
				this.characters[i].addMain(new Character(mains[z]));
			}
			var secondaries = secondaryTag.getElementsByTagName('character');
			for (var k =0;k<secondaries.length;k++) {
				this.characters[i].addSecondary(new Character(secondaries[k]));
			}
		}
		this.showCharacters(this.defaultBook);
	},
	
	showCharacters: function (bookNum) {
		if (!bookNum) {var bookNum = 1;}
		bookNum = bookNum-1;
		
		var charactersContainer = lib.$('kbsCharactersContainer');
		charactersContainer.innerHTML = '';
		
		var bTitle = document.createElement('h2');
		bTitle.appendChild(document.createTextNode(this.titles[bookNum]));
		charactersContainer.appendChild(bTitle);
		
		var mH = document.createElement('p');
		mH.className = 'kbsCharacterHeader';
		mH.appendChild(document.createTextNode(this.characters[bookNum].getMainTitle()));
		charactersContainer.appendChild(mH);
		
		var mainChars = this.characters[bookNum].getMain();
		for (var i=0;i<mainChars.length;i++) {
			var n = document.createElement('p');
			n.className = 'kbsCharacterTxt';
			n.innerHTML = mainChars[i].getName();
			charactersContainer.appendChild(n);
			
			var b = document.createElement('p');
			b.className = 'kbsCharParTxt';
			b.innerHTML = mainChars[i].getBio();
			charactersContainer.appendChild(b);
		}
		
		var sH = document.createElement('p');
		sH.className = 'kbsCharacterHeader';
		sH.appendChild(document.createTextNode(this.characters[bookNum].getSecondaryTitle()));
		charactersContainer.appendChild(sH);
		
		var secChars = this.characters[bookNum].getSecondary();
		for (var z=0;z<secChars.length;z++) {
			var n = document.createElement('p');
			n.className = 'kbsCharacterTxt';
			n.innerHTML = secChars[z].getName();
			charactersContainer.appendChild(n);
			
			var b = document.createElement('p');
			b.className = 'kbsCharParTxt';
			b.innerHTML = secChars[z].getBio();
			charactersContainer.appendChild(b);
		}
	}
};