// Copyright (C) 2007-2008 Stephane Lavergne <http://www.imars.com/>
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along
// with this program. If not, see <http://www.gnu.org/licenses/>.

// Require another JavaScript, if not already included / object not found.
// Return true if the object was found or could be loaded, false on error.
//
// To keep code lean, I rely on XMLHttpRequest() to eval(). I no longer use
// DOM script element addition to head because it required readyState
// monitoring which cannot be done synchronously in JS 1.5.
//
// CAUTION: The XMLHttpRequest way might NOT benefit from the browser's cache!
// If your application reloads the entire page more than occasionally,
// consider hard-coding script tags instead, or even bundling your libraries
// and code into a single production file. (See README.txt on how to use my
// Makefile for this purpose.)

imars.require = function(src) {
	var present = false;
	for (var i = 0, max = imars.includes.length; i < max; i++) {
		if (imars.includes[i].toLowerCase() == src.toLowerCase()) {
			present = true;
		};
	};
	if (present) {
		return true;
	};

	// This way if both methods below fail, anyway we won't try twice.
	imars.includes.push(src);

	// Check the window namespace for the exact name supplied.
	var ss = src.split('.');
	var missing = true;
	// Not the prettiest, but fast and avoids using eval() in awkward ways.
	switch (ss.length) {
		case 1:
			missing = !(window[ss[0]] !== undefined);
			break;
		case 2:
			missing = !((window[ss[0]] !== undefined) && (window[ss[0]][ss[1]] !== undefined));
			break;
		case 3:
			missing = !((window[ss[0]] !== undefined) && (window[ss[0]][ss[1]] !== undefined) && (window[ss[0]][ss[1]][ss[2]] !== undefined));
			break;
		case 4:
			missing = !((window[ss[0]] !== undefined) && (window[ss[0]][ss[1]] !== undefined) && (window[ss[0]][ss[1]][ss[2]] !== undefined) && (window[ss[0]][ss[1]][ss[2]][ss[3]] !== undefined));
			break;
		case 0:
		default:
			// WARNING: Nothing to check.
	};
	if (!missing) return true;

	srcurl = (src[0] == '/') ? src : imars.jsbase + src;
	if (!srcurl.match(/\.js$/)) srcurl += '.js';

	// In both MSIE 6 and Firefox 3, using appendChild with a script/src is not
	// satisfactory because both browsers load the scripts in parallel with the
	// main script, and the objects they define may become available at any
	// time unpredictably, NOT immediately.
	//
	// The solution to this is to use XMLHttpRequest synchronously to gather
	// the source, and then to simply eval, easier than modifying the DOM to
	// add a script tag in head.
	//
	// Note that this is a stripped down copy of imars.net.post().
	var req = false;
	if (typeof(XMLHttpRequest) != 'undefined') req = new XMLHttpRequest();
	else {
		// Try the old MSIE ways...
		try { req = new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch(e) {
			try { req = new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch(e) {
				try { req = new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) {
					try { req = new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) {
						req = false;
					};
				};
			};
		};
	};
	if (req) {
		req.open("GET", srcurl, false);
		req.send(null);
		if (req.status == 200) {
			eval(req.responseText);
			return true;
		};
	};

	return false;

};
