/**
 * This file is reponsible for managing the js library of classes and functions
 *
 * @author Richard Hallows
 * @author pete goodman
*/
var LibraryManager = {

	/**
	 * The path to the root of the site
	 *
	 * @var string path 
	 */
	path: null,
	
	/**
	 * Flag to indicate if we're in the cms or not
	 *
	 * @var bool is cms flag 
	 */
	iscms: null,
	
	/**
	 * The class of the current page
	 *
	 * @var string pageClass 
	 */
	pageClass: null,
	
	/**
	 * The id of the current page
	 *
	 * @var string pageId
	 */
	pageId: null,
	
	
	/**
	 * all javascript functions to call when the DOM of the page has loaded
	 *
	 * @var array loadEvents
	 */
	loadEvents: [],
	
	/**
	 * initialise the library manager
	 *
	 * @return void  
	 */
	initialise: function() {

		this.calculatePath();
		this.calculateState();
		
		//import either the site or cms library manager
		if (this.iscms) {
			this.require('cmslibrarymanager.js');
		} else {
			this.require('sitelibrarymanager.js');	
		}

		// add the initial on dom load event to calculate the page class and id
		this.addLoadEvent( 
			function() {
				LibraryManager.calculatePageDetails();
			}
		);
	},
	
	
	/**
	 * Calculates and sets the relative path from the js library to the root
	 *
	 * @return void  
	 */
	 calculatePath: function() {
		
		// condition : is object var already set?
		if (this.path === null) {
			
			// get path from LibraryManager javascript include string
			var scriptTags = document.getElementsByTagName("script");
			for(var i=0;i<scriptTags.length;i++) {
				if(scriptTags[i].src && scriptTags[i].src.match(/librarymanager\.js(\?.*)?$/)) {
					this.path = scriptTags[i].src.replace(/librarymanager\.js(\?.*)?$/,'');
					break;
				}
			}
		}
	},
	
	
	/**
	 * Calculates state of site, are we in cms or not?
	 *
	 * @return void  
	 */
	 calculateState: function() {
		
		// condition : is object var already set?
		if (this.iscms === null) {
			// condition : is _cms in url?
			if(location.href.match(/_cms/)) {
				this.iscms = true;
			} else {
				this.iscms = false;
			}
		}
	},

	
	/**
	 * Calculates the current page class and id 
	 *
	 * @return void  
	 */
	calculatePageDetails: function() {
		this.pageId = document.getElementsByTagName("body")[0].id; 
		this.pageClass = document.getElementsByTagName("body")[0].className;
	},	
	
	
	/**
	 * Includes a js file
	 * 
	 * @param string libraryfile The path from the js library root to the file
	 *
	 * @return void  
	 */
	require: function(libraryfile) {
		document.write('<script type="text/javascript" src="'+ this.path + libraryfile +'"></script>');
	},
	
	
	/**
	 * function to add event-listeners (cross-browser compatible)
	 * By John Resig - http://ejohn.org/projects/flexible-javascript-events/
	 * 
	 * @param obj object the html element object to attach the event to
	 * @param type string the event type (e.g. 'load', 'keypress', 'click')
	 * @param fn string the name of the function to call  		
	 *
	 * @return void  
	 */
	addEvent: function (obj, type, fn) {
		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 if (obj.addEventListener) {
	     	obj.addEventListener(type, fn, false);
		} else {
			var oldfn = obj['on'+type];
			if (typeof obj['on'+type] != 'function') {
			     obj['on'+type] = fn;
			} else {
			     obj['on'+type] = function() {
			       oldfn();
			       fn();
			     };
			}
		}
	 },


	/**
	 * function to remove event-listeners (cross-browser compatible)
	 * also by John Resig
	 * 
	 * @param obj object the html element object to remove the event from
	 * @param type string the event type
	 * @param fn string the name of the function name to remove   		
	 *
	 * @return void  
	 */
	 removeEvent: function(obj, type, fn) {
	   	if (obj.detachEvent) {
	    	obj.detachEvent('on'+type, obj[type+fn]);
	    	obj[type+fn] = null;
	   	} else {
	    	obj.removeEventListener(type, fn, false);
		}
	 },
	
	
	/**
	 * Ensures functions are only run once the core library is loaded
	 * Detects when the DOM tree has loaded, then triggers all onload events
	 * 
	 * @param function func The function to execute
	 *
	 * @return void  
	 */
	addLoadEvent: function (func) {
		
		// add the latest event to the list of DOMload events - Win IE5 doesn't support Array.push so...
		this.loadEvents[this.loadEvents.length] = func;
		
		// test whether the DOM load event listener has been added yet - only needs adding the first time
		if (this.loadEvents.length == 1) {

			// detect whether one form of dom load is supported
			var domLoadSupported = false;

			// firefox & Opera 9 support natively DOM load
			if (document.addEventListener) {
				document.addEventListener("DOMContentLoaded", this.onDomLoaded, null);
				domLoadSupported = true;
			}
		
			// safari & konqueror have an alternative DOM load detector 
			if (/KHTML|WebKit/i.test(navigator.userAgent)) { 
				var _timer = setInterval(function() {
					if (/loaded|complete/.test(document.readyState)) {
						clearInterval(_timer);
						delete _timer;
						LibraryManager.onDomLoaded();
					}
				}, 10);
				domLoadSupported = true;
			}
		
			// Win IE uses a script with a 'defer' attribute for DOM load detection  
			/*@cc_on @*/
			/*@if (@_win32)
			var proto = "javascript:void(0)";
			if (location.protocol == "https:") proto = "src=//0";
			document.write("<scr"+"ipt id=__ie_onload defer src=" + proto + "><\/scr"+"ipt>");
			var script = document.getElementById("__ie_onload");
			script.onreadystatechange = function() {
			    if (this.readyState == "complete") {
			        LibraryManager.onDomLoaded();
			    }
			};
			domLoadSupported = true;
			/*@end @*/

			// legacy browsers - load events added when everything has finished loading
			if (!domLoadSupported) {
				this.addEvent(window, 'load', this.onDomLoaded);
			}
		}
	},
	
	
	/**
	 * Private function called when the DOM tree has loaded, 
	 * to cycle through and execute all on load events
	 * 
	 * @return void  
	 */
	onDomLoaded: function () {
		if (arguments.callee.done) return;
		arguments.callee.done = true;
		for (var i=0; i<LibraryManager.loadEvents.length; i++) {
		 	LibraryManager.loadEvents[i]();
		}
	}
}

//start the js library manager
LibraryManager.initialise();