/**
 * This file is reponsible for managing the js library of classes and functions
 */
LibraryManager = {

	// String : The path to the root of the site
	path: null,
	
	// Boolean: Flag to indicate if we're in the cms or not
	iscms: null,
	
	// Boolena: Flag to indicate if the JS is generated or static
	isgenerated: false,

	// Array: all javascript functions to call when the DOM of the page has loaded
	loadEvents: [],
	
	// Array: all of the subloaded script files called via the require function
	requiredScripts: [],
	
	// String: The class of the current page
	pageClass: null,
	
	// String: The id of the current page
	pageId: null,


	/**
	 * initialise the library manager
	 *
	 * @return void  
	 */
	initialise: function() {

		// set the path to the js library home
		this.calculatePath();

		// check whether this is a live site or CMS
		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 libman = document.getElementById("librarymanager");
			if (!libman) return false;
			
			// check for a filename extension - is it static JS?
			if (libman.src.indexOf('librarymanager.js') != -1) {

				// if so, remove the filename before setting the path 
				this.path = libman.src.replace(/librarymanager\.js(\?.*)?$/,'');
				
			// no filename, so it is generated JS
			} else {
				this.isgenerated = true;
				this.path = libman.src;
			}
		}
	},
	
	
	
	/**
	 * 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) {
		
		// array to contain all requested files
		var requiredFiles = [];
		
		// check if the libraryfile is a string (deprecated) or an array
		if (typeof libraryfile == "string") {
			
			// turn it into an array
			requiredFiles.push(libraryfile);
		
		} else {
			requiredFiles = libraryfile;
		}

		// if the library is static, insert each script
		if (!this.isgenerated) {
			for (var i=0; i < requiredFiles.length; i++) {
				document.write('<script type="text/javascript" src="'+ this.path + requiredFiles[i] +'"></script>');
			};
		
		// if the script is generated, append JSON object
		} else {
			for (var x=0; x < requiredFiles.length; x++) {
				this.requiredScripts.push(requiredFiles[x]);
			}
		}
	},
	

	
	/**
	 * 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);
			}
		}
	},
	

		
	/**
	 * 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);
		}
	 },
		
		
		
	/**
	 * 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();
