/**
 * @namespace  Namespace for Presto JavaScript Library Loader.
 */
if ( ! window.Presto ) {
	var Presto = {};
}


(function( Presto, window, document, undefined ) {

// For display of logging messages
Presto.debug = false;


// Create empty function for reference
Presto.noop = function(){};


// Setup an extension mechanism on the Presto namespace
Presto.extend = function(){
	var args = Array.prototype.slice.call( arguments ), i = -1, l = args.length, name, copy, target;

	if ( l === 1 ) {
		target = this;
	} else {
		target = args[ 0 ];
		i = 0;
	}

	for ( ; ++i < l; ) {
		copy = args[ i ];
		for ( name in copy ) {
			target[ name ] = copy[ name ];
		}
	}

	return target;
};


// Basic looping with closure
Presto.each = function( items, fn ) {
	var i = -1, l = items.length;
	fn = fn || Presto.noop;

	if ( l === undefined ) {
		for ( i in items ) {
			if ( fn.call( items[ i ], i, items[ i ] ) === false ) {
				break;
			}
		}
	}
	else {
		for ( ; ++i < l; ) {
			if ( fn.call( items[ i ], i, items[ i ] ) === false ) {
				break;
			}
		}
	}

	return items;
};


// Access the search query parameters
Presto.Param = (function(){
	var props = ( window.location.search || '' ).replace( /^\?/, '' ).split('&'), i = -1, l = props.length, params = {}, parts, name, value, lower;

	for ( ; ++i < l; ) {
		parts = props[ i ].split('=');
		name = parts[ 0 ];

		if ( ! name || name.length < 1 ) {
			continue;
		}

		// Decode Values
		value = parts.length > 1 ? decodeURIComponent( parts[ 1 ] ) : 'true';

		params[ name ] = value === undefined || value.length < 1 || value === 'undefined' ? undefined :
			value === 'true' ? true :
			value === 'false' ? false :
			value === 'null' ? null :
			value == parseFloat( value ) ? parseFloat( value ) :
			value;
	}

	return params;
})();


// Ondemand console exposure
(function(){
	var console = {}, names = [
		"log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
		"group", "groupCollapsed", "groupEnd", "time", "timeEnd", "count",
		"trace", "profile", "profileEnd"
	];


	// Make sure we are working with 
	if ( ! window.console ) {
		window.console = {};
	}

	for ( var i = -1, l = names.length; ++i < l; ) {
		console[ i ] = window.console[ names[ i ] ] || Presto.noop;
	}

	// Allow ondemand change of console exposure
	Presto.Console = function( expose ) {
		// Store the current state
		Presto.debug = expose;

		for ( var i = -1, l = names.length; ++i < l; ) {
			window.console[ names[ i ] ] = expose || names[ i ] === 'error' ? console[ i ] : Presto.noop;
		}

		if ( Presto.Console.hasDebug ) {
			window.console.log = window.console.debug;
		}

		// Show debugging mode is on
		window.console.log('Debug Mode is On');
	};

	// Need to store initial console info
	Presto.Console.hasConsole = typeof window.console == 'object';
	Presto.Console.hasDebug = ( Presto.Console.hasConsole && window.console.debug );
	Presto.Console._console = window.console || {};

	// Allow for param query overwrite of basic base debug exposure
	Presto.Console( Presto.Param.debug !== undefined ? Presto.Param.debug : Presto.debug );
})();


// Browser detection, NOT RELIABLE
(function( ua ) {
	Presto.browser = { mobile: false };
	var mobile = "iphone,ipad,ipod,symbian,android,windows ce,blackberry,palm".split(','),
		platforms = "webkit,msie,opera,mozilla".split(','),
		device, i, l;
	
	// Run mobile testing first
	for ( i = -1, l = mobile.length; ++i < l; ) {
		device = mobile[ i ];
		if ( ua.indexOf( device ) > -1 ) {
			Presto.browser[ device ] = true;
			Presto.browser.mobile = true;
		}
		else {
			Presto.browser[ device ] = false;
		}
	}

	// Now do platform testing
	for ( i = -1, l = platforms.length; ++i < l; ) {
		device = platforms[ i ];
		Presto.browser[ device ] = ua.indexOf( device ) > -1;
	}
})( navigator.userAgent.toLowerCase() );


// Transfer the Object.extend to Presto.extend (for backwards compatibility)
Object.extend = function(){
	return Presto.extend.apply( this, arguments );
};


/**
 * @private
 * extending javascript Array class to have Prototype.js like method to return an array without matching element
 */
Array.prototype.without = function(arrElement) {
	var arrWithout = [];
	
	for (var i = 0, loopLen = this.length; i < loopLen; i++) {
		if (arrElement !== this[i]) {
			arrWithout.push(this[i]);
		}
	}
	
	return arrWithout;
};

/**
 * @private
 * extending javascript Array class to have case-insensitive indexOf method (iindexOf)
 */
Array.prototype.iindexOf = function(k) {
	for (var i = 0, j = this.length; i < j; i++) {
		if (typeof this[i] === "string" && this[i].toLowerCase() === k.toLowerCase()) {
			return i;
		}
	}
	
	return -1;
};


/**
 * @private
 */
Presto.onDemand = {

	log: [],

	reloadAlways: Presto.Param.reloadAlways,

	queue: [],
	
	// HELP-202
	currentIntervals: [],

	pending: null,

	stopLoadingScripts: function() {
		while (this.queue.length > 0) {
			var req = this.queue.shift();
			req.callback.onFailure.apply(req.callback.scope, ['Aborted']);
		}
		this.pending = null;
	},

	checkCondition: function() {

		var p = this.pending, self = this;
		if (!p) {
			return;
		}
		
		var requestComplete = function(t) {
			//Presto.onDemand.log.push((t || ' ')+'e: '+p.url);
			if (!p.requestCompleted) {

				if (p.callback) {
					var arr = [p.url];
					if (p.args) {
						for (var i = 0; i < p.args.length; i++) {
							arr.push(p.args[i]);
						}
					}
					p.callback.onSuccess.apply(p.callback.scope, arr);
				}

				p.requestCompleted = true;
			}
			if (self.queue.length > 0) {
				var req = self.queue.shift();
				self.requireScript(req.url, req.callback, req.condition, req.args);
			} else {
				self.pending = null;
			}
		},
		
		clearAnyInterval = function(url){
		   
			var clearedIntervals = [], i;

			for ( i = 0; i < self.currentIntervals.length; i++) {
				if (self.matchUrl(url, self.currentIntervals[i].url)){
					clearInterval(self.currentIntervals[i].interval);
					clearedIntervals.push(i);
				}
			}
		
			// probably shouldnt splice within the for loop, so we do it after
			for ( i = 0; i < clearedIntervals.length; i++) {
				self.currentIntervals.splice(i, 1);
			}
		};
		
		clearAnyInterval(p.url, true);
		
		if (p && p.condition && typeof p.condition == 'function') {

            var loaded = false;
            
            try {
                loaded = p.condition();
            } catch (e){}

			if (!loaded) {

				var startTime = Presto.now(),

				interval = setInterval(function() {

                    try {
                        loaded = p.condition();
                    } catch (e){}

					if (loaded) {
						clearAnyInterval(p.url);
						clearInterval(interval);
						requestComplete('t');
					} else {
						if ( Presto.now() - startTime > Presto.LOAD_TIMEOUT ) {
							if (p.callback) {
								p.callback.onFailure.apply(
									p.callback.scope,
									[ Presto.LOAD_TIMEOUT_DISP + ' second time out.' ]
								);
								self.stopLoadingScripts();
							}
							clearInterval( interval );
						}
					}
				}, 10);
 
				// HELP-202
				this.currentIntervals.push({
						url: p.url,
						interval: interval
				});
				// end HELP-202
				
			} else {
				requestComplete('c');
			}
		} else {
			requestComplete('-');
		}
	},
	/**
	 * @private
	 * Returns a url with all /./ and /../ parts removed from url.
	 */
	cleanUrl: function(url){
		if(url.match(/\/\.\//)){
			url = url.replace(/\/\.\//g, '/');
		}

		while(url.match(/\/[^\/]*(\/\.)*\/\.\./)){
			url = url.replace(/\/[^\/]*(\/\.)*\/\.\./, '');
		}
		return url;
	},

	matchUrl: function(url, otherUrl) {

		function endsWith(src, pattern) {
				var d = src.length - pattern.length;
				return d >= 0 && src.lastIndexOf(pattern) === d;
			}

		if (url && otherUrl) {

			// REAP 8312 :  replace anything like this : /foo/bar/../ with /foo/
			if(url.match(/\/\w+\/\.\./)){
				url = url.replace(/\/\w+\/\.\./g, '');
			}

            // REAP-12780 trim off any Presto.Guid if attached 
            if(this.reloadAlways && /[&?]_\d+$/.test(otherUrl)){
                otherUrl = otherUrl.substring(0, otherUrl.lastIndexOf("_")-1);
            }

			if (/(http|https):\/\//.test(url)) {

				// then we need to check we're not trying to load a script
				// from another hub

				// trim off the ip address
				var relUrl = url.substring(url.indexOf('//') + 2);
				relUrl = relUrl.substring(relUrl.indexOf('/'));

				if (endsWith(otherUrl, relUrl)) {
					return true;
				}
			}
			if (endsWith(otherUrl, url)) {
				//console.log(url + ' script already exists.. skipping');
				return true;
			}
		}
		return false;
	},
	requireScript: function(url, callback, condition) {

		url = this.cleanUrl(url);

		var self = this;
		
		var request = {
			url: url,
			callback: callback,
			condition: condition,
			args: Array.prototype.slice.call(arguments, 3)
		};

		if (this.pending && !this.pending.requestCompleted) {
			//console.log('queue '+url);
			this.queue.push(request);
			return;
		}

		this.pending = request;

		//console.log('load '+url);
		if (condition) {
			//condition();
		}

		var scripts = document.getElementsByTagName('script');
		var found = false;
		if (scripts) {
			for (var i = 0; i < scripts.length; i++) {

				if (this.matchUrl(url, scripts[i].src)) {
					found = true;
					//console.log("Script already loaded");
					break;
				}
			}
		}

		if (!found) {
			//console.log(url + ' script loading');
			var p = this.pending;

			//Presto.onDemand.log.push('s : '+p.url);

			var script = document.createElement('script');
			script.setAttribute('type', 'text/javascript');
			if (p.callback || p.condition) {

				script.onreadystatechange = (function(pending) {
					return function(response) {

						// jcp :
						// notice on IE, when we refresh, we might only see complete event
						// also, setting handler to null doesnt prevent complete and loaded events
						// coming through, may need to delete function.
						if (this.readyState == "loaded" || this.readyState == 'complete') {
							//console.log('onreadystatechange, '+ this.readyState, self.pending.url);
							this.onreadystatechange = null;
							if (pending == self.pending) {
								self.checkCondition();
							}
						}
					};
				})(p);
				// Firefox
				script.onload = function(response) {
					//console.log('onload', self.pending.url);
					script.onload = null;
					self.checkCondition();
				};
			}
			var head = document.getElementsByTagName('head')[0];
			var insert = head.appendChild(script);
			script.src = this.reloadAlways ? p.url + ( p.url.indexOf('?') > -1 ? '&' : '?' ) + '_' + Presto.Guid() : p.url;

			//check for queue status update after the timeout period
			setTimeout(function() {
				if (self.pending == p) {
					//there is a timeout error
					p.callback.onFailure.apply(p.callback.scope, [Presto.LOAD_TIMEOUT_DISP + ' second time out.']);
					self.stopLoadingScripts();
				}
			}, Presto.LOAD_TIMEOUT);
		} else {
			//console.log('script found,'+ self.pending.url, (self.pending.condition?'condition':''));
			self.checkCondition();
		}
	},

	requireCSS: function(url, callback) {
		var links = document.getElementsByTagName('link');
		var found = false;
		
		url = this.cleanUrl(url);

		if (links) {
			for (var i = 0; i < links.length; i++) {
				if (this.matchUrl(url, links[i].href)) {
					found = true;
					break;
				}
			}
		}
		if (!found) {
			var link = document.createElement('link');
			link.setAttribute('type', 'text/css');
			link.setAttribute('rel', 'stylesheet');
            // Added reloadAlways to CSS in cases where CSS needs to be reloaded
            var href = this.reloadAlways ? url + ( url.indexOf('?') > -1 ? '&' : '?' ) + '_' + Presto.Guid() : url;
            link.setAttribute('href', href);
            
			// @todo: <link> does not have the onload property like <script> .. hence callback is not possible
			var head = document.getElementsByTagName('head')[0];
			head.appendChild(link);
			//link.href = href;
			if ( callback ) {
				callback.onSuccess();
			}
		} else {
			if ( callback ) {
				callback.onSuccess();
			}
		}
	}

};


})( Presto, this, this.document );



//definition of loader methods
(function( Presto, window, document, undefined ) {

	var loading = 0,

	errors = [],

	basePath = "",

	// callback functions waiting for load completion
	onLoadCallbacks = [],

	loadedLibs = {},

	// jcp : keep track of scripts loaded by doc write
	docLoadedScripts = {},
	
	// jcp: keep track of css loaded by doc write
	docLoadedCSS = {};

	function updateScriptLoadStatus(scriptName, error) {
		//set a flag to mark that the script has been loaded
		loadedLibs[scriptName] = error ? false : true;
		attemptCallback();
	}
	

	function attemptCallback() {
		if (loading <= 0 && onLoadCallbacks.length > 0) {
			var callbacks = onLoadCallbacks,
            loadErrors = errors;
            errors = [];
			onLoadCallbacks = [];
			for(var i=0; i < callbacks.length; i++){
				var callback = callbacks[i];

				if (callback.onSuccess && !loadErrors.length) {
					callback.onSuccess.apply(callback.scope || this);
				} else if (callback.onFailure) {
					callback.onFailure.apply(callback.scope || this, loadErrors);
				}
			}
		}
	}
	
	
	function addErrorForLib(fileName, libName, message) {
		errors.push("There was an error while loading '" + fileName + (libName ? "' in '" + libName + "' library - " : " - ") + (message ? message : ""));
	}

	//get current script location
	var scripts = document.getElementsByTagName('script'),
			LOADER_SCRIPT_REGEX = /loader.js(\?.*)?$/;//based on current file's name

	for (var i = 0; i < scripts.length; i++) {
		if (LOADER_SCRIPT_REGEX.test(scripts[i].src)) {
			var lastPathSepIndex = scripts[i].src.lastIndexOf("/");
			if (lastPathSepIndex > 0) {
				basePath = scripts[i].src.substring(0, lastPathSepIndex);
			}
		}
	}
	// IE7 doesn't reveal full paths, so assume that if direct path isn't provided,
	// we can safely pull the base path from the URL
    // jcp : wouldnt it include /prestohub/ ?
	if ( basePath === 'jsapi' || basePath === '/prestohub/jsapi') {
		//FIX for IE - we have an issue with the above line as it does not take care of query string
		//Putting in a fix using the following lines
		var fullPath = window.location.href;
		fullPath = fullPath.split('?')[0];//remove query string
		fullPath = fullPath.split('#')[0];//remove # in URL
		basePath = fullPath.replace( window.location.pathname, '/prestohub/jsapi' );
	}
	if (!basePath) {
		basePath = ".";
	}
	window.BASE_PATH = basePath;
	

	Presto.extend({
		// Timeout (in miliseconds)
		LOAD_TIMEOUT: 20000,
		// Timeout (in seconds)
		LOAD_TIMEOUT_DISP: 20,

		// Expose the base path on the presto namespace
		BASE_PATH: basePath,
		HUB_PATH: basePath.replace(/\/jsapi$/, ''),
		PRESTO_PATH: basePath.replace(/\/prestohub\/jsapi$/, '/presto'),

		// For checking if inside frame
		iframed: self !== top ,

		// Error handling
		error: function( e ) {
			if ( Presto.ui && Presto.ui.handleException ) {
				return Presto.ui.handleException( e );
			}
			console.error( e );
		},

		// Warnings
		warn: function(){
			console.warn.apply( console, arguments );
		},

		// Current Timestamp (use native Date.now if possible)
		now: Date.now || function(){
			return ( new Date() ).getTime();
		},

		// Simple proxy function for scoping
		proxy: function( scope, fn ) {
			return function(){
				fn.apply( scope, arguments );
			};
		},

		/**
		 * Always returns a unique-id
		 */
		Guid: (function(){
			var id = Date.now ? Date.now() : ( new Date() ).getTime();
			return function(){
				return ++id;
			};
		})(),

		/**
		 * Global notification handler for loadconfirmation so libs added
		 * can just signal a flag that they've been loaded
		 */
		Flag: function( name, value ) {
			Presto.Flag[ name ] = arguments.length < 2 ? true : value;
		},

		/**
		 * @private
		 * Returns true if the Presto Loader is busy.
		 */
		isLoadingLib: function() {
			return (loading > 0);
		},

		/**
		 * <p>Loads the JavaScript library specified by absolute or relative URL.
		 * Relative URLs are relative to the path to the Presto JS Library Loader. </p>
		 * @param {String} scriptSrc  The URL to the JavaScript library to load. 
		 */
		loadScript: function(scriptSrc, condition) {
			if (loadedLibs[scriptSrc] === true) {
				return;
			}
			loading++;
			Presto.onDemand.requireScript(scriptSrc, {
				onSuccess:function() {
					loading--;
					updateScriptLoadStatus(scriptSrc, true);
				},
				onFailure:function(message) {
					loading--;
					addErrorForLib(scriptSrc, null, message);
					updateScriptLoadStatus(scriptSrc, false);
				}
			}, condition);
		},

		/**
		 * <p>Loads the CSS stylesheet specified by absolute or relative URL.
		 * Relative URLs are relative to the path to the Presto JS Library Loader. </p>
		 * @param {String} cssSrc  The URL to the CSS library to load. 
		 */
		loadCSS: function(cssSrc) {
			if (loadedLibs[cssSrc] === true) {
				return;
			}
			loading++;
			Presto.onDemand.requireCSS(cssSrc, {
				onSuccess:function() {
					loading--;
					updateScriptLoadStatus(cssSrc, true);
				},
				onFailure:function(message) {
					loading--;
					addErrorForLib(cssSrc, null, message);
					updateScriptLoadStatus(cssSrc, false);
				}
			});
		},

		/**
		 * <p>Loads the JavaScript library specified by name and optional version, handling all
		 * dependencies. This JS library must be configured in <code>libraries-config.js</code>. </p>
		 * <p>Loading can be handled on demand or by directly writing a &lt;script&gt; tag to the 
		 * DOM based on the <code>useDocWrite</code> parameter. Direct writes ensure that loading 
		 * is handled synchronously, in a concrete order, but must occur before the DOM is fully 
		 * loaded. Loading on demand is asynchronous, providing better performance and can occur after 
		 * the DOM is loaded. On demand loading, however, does not guarantee any loading order.</p>
		 * @param {String} libName  The configured name of the JavaScript library to load. 
		 * @param {String} version  Optionally, the specific version of this library to load. If omitted,
		 *						  the default version is loaded.
		 * @param {Boolean} useDocWrite  Optionally, whether to directly write a &lt;script&gt; tag (true) or
		 *							   load this library on demand (false). 
		 */
		loadLib: function(libName, version, useDocWrite) {

			if (loadedLibs[libName] === true) {
				return;
			}

			if(useDocWrite){
				Presto.loadLibByWrite(libName, version);
				return;
			}

			var lib = Presto.libraries[libName],
					curVersion,
					path = [],i,libPath=lib && lib.libPath ?lib.libPath:"",
					isAbsolute=libPath.match(/^http[s]*\:\/\//)!==null;
			libPath = (libPath[0] != "/" && !isAbsolute? "/" : "") + libPath;
			if(!isAbsolute){
				libPath = basePath + libPath;
			}
			if (lib) {

				if (lib.dependsOn) {
					for (i = 0; i < lib.dependsOn.length; i++) {
						var reqLib = lib.dependsOn[i];
						if (typeof(reqLib) == "string") {
							Presto.loadLib(reqLib);
						} else {
							Presto.loadLib(reqLib.library, reqLib.version);
						}
					}
				}

				if (version && lib.versions[version]) {
					curVersion = version;
				} else {
					curVersion = lib.defaultVersion;
				}

				// load scripts
				var scripts = lib.versions[curVersion].scripts;
				if ( scripts ) {
					Presto.each( scripts, function( i, script ) {
						// Account fo unloaded file 
						loading++;

						Presto.onDemand.requireScript(
							// Path to script
							libPath + (script.charAt(0) == "/" ? "" : "/") + script,

							// Callbacks
							{
								onSuccess: function() {
									loading--;
									updateScriptLoadStatus( libName, true );
								},
								onFailure: function( message ) {
									loading--;
									addErrorForLib( script, libName, message );
									updateScriptLoadStatus( libName, false );
								}
							},

							// Condition
							( i == scripts.length - 1 ? lib.loadConfirmation : null )
						);
					});
				}


				var styleSheets = lib.versions[curVersion].css;
				if ( styleSheets ) {
					Presto.each( styleSheets, function( i, sheet ) {
						// Account fo unloaded file 
						loading++;

						// Load stylesheet
						Presto.onDemand.requireCSS( libPath + (sheet.charAt(0) == "/" ? "" : "/") + sheet, {
							onSuccess: function() {
								loading--;
								updateScriptLoadStatus( libName, true );
							},
							onFailure: function( message ) {
								loading--;
								addErrorForLib( sheet, libName, message );
								updateScriptLoadStatus( libName, false );
							}
						});
					});
				}
				var winVars = lib.versions[ curVersion ].globalVariables;
				if ( winVars ) {
					Presto.each( winVars, function( name, value ) {
						window[ name ] = value;
					});
				}
			} else {
				addErrorForLib(libName);
			}
		},

		/**
		 * @private
		 */
		loadLibByWrite: function(_lib,version){
			var alreadyGot = {};

			function getScriptList(libName, _version) {
				var scriptList = [];
				var library = Presto.libraries[libName];

				if (library && !loadedLibs[libName]) {
					_version = _version?_version:library.defaultVersion;

					var requiredLib = library.versions[_version];
					var i = 0, loopLen = 0;

					alreadyGot[libName] = true;
					loadedLibs[libName] = true;

					if (library.dependsOn) {
						for (i = 0, loopLen = library.dependsOn.length; i < loopLen; i++) {
							scriptList = scriptList.concat(getScriptList(library.dependsOn[i]));
						}
					}

					var ownScriptList = [];
					var script = null;

					for (i = 0, loopLen = requiredLib.scripts.length; i < loopLen; i++) {
						script = requiredLib.scripts[i];
						
						if (script) {
							var scriptLoc = library.libPath + (library.libPath.charAt(library.libPath.length - 1) == '/' ? '' : '/') + (script.charAt(0) == '/' ? script.substring(1, script.length) : script);
							var isAbsolute = (scriptLoc.match(/^http[s]*\:\/\//));
							scriptLoc = (!isAbsolute ? (BASE_PATH.charAt(BASE_PATH.length - 1) == '/' ? BASEPATH.substring(0, BASE_PATH.length - 1) : BASE_PATH) : '') + (isAbsolute ? '' : '/') + (scriptLoc.charAt(0) == '/' ? scriptLoc.substring(1, scriptLoc.length) : scriptLoc);
							ownScriptList.push(scriptLoc);
						}
					}

					scriptList = scriptList.concat(ownScriptList);

					if (requiredLib.globalVariables){
						var globs = requiredLib.globalVariables;
						for ( i in globs ) {
							if ( typeof globs[ i ] != 'function' ) {
								window[ i ] = globs[ i ];
							}
						}
					}
				}

				scriptList = scriptList.without( undefined ).without('');
				return scriptList;
			}

			function getCSSList(libName, _version) {
				var cssList = [], ownCSSList=[];
				var library = Presto.libraries[libName];

				if (library && !alreadyGot[libName]) {
					_version = _version?_version:library.defaultVersion;

					var requiredLib = library.versions[_version];
					var i = 0, loopLen = 0;

					alreadyGot[libName] = true;
					loadedLibs[libName] = true;//just in case no JS is loaded as part of this lib

					if (library.dependsOn) {
						for (i = 0, loopLen = library.dependsOn.length; i < loopLen; i++) {
							var dependsOnLib = library.dependsOn[i];

							if(typeof dependsOnLib == 'string'){
								cssList = cssList.concat(getCSSList(dependsOnLib));
							} else if(dependsOnLib.name){
								cssList = cssList.concat(getCSSList(dependsOnLib.name, dependsOnLib.version));
							} else {
								console.error('Unrecognised library.dependsOn entry structure', dependsOnLib);
							}
							// jcp: say we have explicily loaded a versioned library, we need to ensure it
							// isnt overridden by a non-versioned library being loaded as a depenency
							// this is a design flaw we need to fix..
							//  if(!loadedLibs[dependsOnLib]){
							// check seems to screw up prestweb search page..
							//	  cssList = cssList.concat(getCSSList(dependsOnLib));
							//  }
						}
					}
					
					if (requiredLib.css) {
						var cssLoc, isAbsolute, sheet;
						for (i = 0, loopLen = requiredLib.css.length; i < loopLen; i++) {
							sheet = requiredLib.css[i];
							cssLoc = library.libPath + (library.libPath.charAt(library.libPath.length - 1) == '/' ? '' : '/') + (sheet.charAt(0) == '/' ? sheet.substring(1, sheet.length) : sheet);
							isAbsolute = (cssLoc.match(/^http[s]*\:\/\//));
							cssLoc = (!isAbsolute ? (BASE_PATH.charAt(BASE_PATH.length - 1) == '/' ? BASEPATH.substring(0, BASE_PATH.length - 1) : BASE_PATH) : '') + (isAbsolute ? '' : '/') + (cssLoc.charAt(0) == '/' ? cssLoc.substring(1, cssLoc.length) : cssLoc);
							ownCSSList.push(cssLoc);
						}
					}
					
					cssList = cssList.concat(ownCSSList);
				}
				
				cssList = cssList.without('').without(undefined);
				return cssList;
			}

			var urlList = getScriptList(_lib,version);
			//console.log(_lib+', js list :', urlList);
			alreadyGot = {};
			var cssList = getCSSList(_lib,version);
			//console.log(_lib+', cssList :', cssList);
			var i = 0, loopLen = urlList.length;
			
			for (; i < loopLen; i++) {
				Presto.loadScriptByWrite(urlList[i]);
			}
			
			for (i = 0, loopLen = cssList.length; i < loopLen; i++) {
				Presto.loadCSSByWrite(cssList[i]);
			}
		},

		/**
		 * @private 
		 */
		loadScriptByWrite: function(script){
			script = Presto.onDemand.cleanUrl(script);
			if(!docLoadedScripts[script]){
				docLoadedScripts[script] = true;
				document.write('<s' + 'cript type="text/javascript" src="' + script + '" ><\/script>');
			}
		},

		/**
		 * @private
		 */
		loadCSSByWrite: function(sheet){
			sheet = Presto.onDemand.cleanUrl(sheet);
			if(!docLoadedCSS[sheet]){
				docLoadedCSS[sheet] = true;
				document.write('<l' + 'ink type="text/css" rel="stylesheet" href="' + sheet + '" />');
			}
		},

		/**
		 * @private
		 */
		addLibraryConfig: function(configObj,overwrite){
			overwrite = (typeof overwrite=='boolean')?overwrite:true;
			var libName = Object.keys(configObj)[0];

			if(!Presto.libraries[libName] || (Presto.libraries[libName] && overwrite)){
				//should we do some sort of checking to see if the config is if proper format?
				Presto.libraries[libName] = configObj[libName];
				return true;
			}
			else{
				return false;
			}
			
					
		},

		/**
		 * <p>Fires when all load requests are complete. This can occur before or after the DOM is fully loaded
		 * depending on whether loading was requested on demand. The configuration object passed to
		 * this method allows you to pass callback functions to handle successful loading or loading 
		 * failures.</p>
		 * @param {Object} callback  A configuration object with the following properties: <br />
		 * @config {Function} onSuccess  A callback function to use when loading is successful. This  
		 *							   callback has a single <code>scope</code> parameter. 
		 * @config {Function} onFailure  A callback function to use when there are loading errors. This
		 *							   callback has two parameters: <code>scope</code>, <code>errors</code>.
		 *							   The errors property contains an error message.  
		 * @config {Object} scope  The object that defines the scope for callback methods. Typically "this".
		 */
		onLoadComplete: function(callback) {
			onLoadCallbacks.push(callback);
			attemptCallback();
		}

	});

	// Load config files
	Presto.loadScriptByWrite( basePath + '/libraries-config.js' );
	Presto.loadScriptByWrite( basePath + '/../custom-libraries-config.js' );

})( Presto, this, this.document );

