var SWAT = {
	_included: {},
	_libs: {},
	_localLibs: {},
	_css: {},
	_localCSS: {},
	_paths: null,
	_cssPaths: null,
	_libNS: new Object(),
	_ajaxListeners: {},
	_moduleLoadListener: [],

	_classCounts: {},

	AjaxPath: null,
	SearchServicePath: null,

	include: function(fileName, loc, module) {
		if(!loc)
			loc = 'project';

		var url = SWAT.Paths[loc] + '/' + fileName;
		if(url in SWAT._included)
			return;

		try {
			new Ajax.Request(url, {
				method: 'get',
				asynchronous: false,
				evalJS: true,
				parameters: {},

				onSuccess: function(transport) {
					SWAT._included[url] = true;
					if(module) {
						for(var i = 0; i < SWAT._moduleLoadListener.length; i++) {
							SWAT._moduleLoadListener[i](module);
						}
					}
				},

				onFailure: function() {
					alert('Failed to load ' + url);
				}
			});
		}
		catch(exc) {
			if(window.console && window.console.dir)
				console.dir(exc);
		}
	},

	includeCSS: function(fileName, loc) {
		if(!loc)
			loc = 'project';

		var url = SWAT.CssPaths[loc] + '/' + fileName;

		var cssNode = document.createElement('link');
		cssNode.type = 'text/css';
		cssNode.rel = 'stylesheet';
		cssNode.href = url;
		cssNode.media = 'screen';
		document.getElementsByTagName('head')[0].appendChild(cssNode);
	},

	use: function(library) {
		if(library in SWAT._libs)
			return;
		var name = library + '.lib.js';
		if(SWAT.UseMinLibJS)
			name += '.min';
		SWAT.include(name, 'uilib', library);
		SWAT._libs[library] = true;
	},

	useLocal: function(library) {
		if(library in SWAT._localLibs)
			return;
		var name = library + '.lib.js';
		if(SWAT.UseMinJS)
			name += '.min';
		SWAT.include(name, 'projectlib', library);
		SWAT._localLibs[library] = true;
	},

	useCSS: function(css) {
		if(css in SWAT._css)
			return;
		SWAT.includeCSS(css + '.lib.css', 'uilib', css);
		SWAT._css[css] = true;
	},

	useLocalCSS: function(css) {
		if(css in SWAT._localCSS)
			return;
		SWAT.includeCSS(css + '.lib.css', 'projectlib', css);
		SWAT._localCSS[css] = true;
	},

	loadCompressed: function(file) {
		SWAT.include(file);
	},

	getProjectJS: function() { return SWAT.Paths.project; },
	getProjectLibJS: function() { return SWAT.Paths.projectlib; },
	getUIJS: function() { return SWAT.Paths.ui; },
	getUILibJS: function() { return SWAT.Paths.uilib },

	getProjectCSS: function() { return SWAT.CssPaths.project; },
	getProjectLibCSS: function() { return SWAT.CssPaths.projectlib; },
	getUICSS: function() { return SWAT.CssPaths.ui; },
	getUILibCSS: function() { return SWAT.CssPaths.uilib },

	addAjaxListener: function(key, cb) {
		if(!(key in SWAT._ajaxListeners))
			SWAT._ajaxListeners[key] = [ cb ];
		else
			SWAT._ajaxListeners[key].push(cb);
	},

	removeAjaxListener: function(key, cb) {
		if(!cb)
			SWAT._ajaxListeners[key] = [];
		if(key in SWAT._ajaxListeners)
			for(var i = 0; i < SWAT._ajaxListeners.length; i++)
				if(SWAT._ajaxListeners[key][i] == cb) {
					SWAT._ajaxListeners[key].splice(i, 1);
					break;
				}
	},

	waitOnAjax: function(keys, cb, updateCb) {
		var keyCount = 0;
		var leftFor = {};
		var finishWait = (function(keys, cb, updateCb, key) {
			keyCount--;
			leftFor[key]--;
			if(updateCb)
				updateCb(key, keyCount, leftFor[key]);
			if(keyCount != 0)
				return;
			for(var i = 0; i < keys.length; i++)
				SWAT.removeAjaxListener(keys[i], finishWait);
			cb();
		}).bind(this, keys, cb, updateCb);
		for(var i = 0; i < keys.length; i++) {
			var keyInfo = keys[i].split(/\//);
			if(keyInfo.length > 1) {
				leftFor[keyInfo[0]] = keyInfo[1];
				keyCount += (1 * keyInfo[1]);
			}
			else {
				leftFor[keyInfo[0]] = 1;
				keyCount++;
			}
			SWAT.addAjaxListener(keyInfo[0], finishWait);
		}
	},

	ajaxFinished: function(key) {
		if(key in SWAT._ajaxListeners) {
			for(var i = 0; i < SWAT._ajaxListeners[key].length; i++)
				if(Object.isFunction(SWAT._ajaxListeners[key][i]))
					SWAT._ajaxListeners[key][i](key);
		}
	},

	addModuleLoadListener: function(listener) {
		SWAT._moduleLoadListener.push(listener);
	},

	removeModuleLoadListener: function(listener) {
		for(var i = 0; i < SWAT._moduleLoadListener.length; i++)
			if(SWAT._moduleLoadListener[i] == listener)
				SWAT._moduleLoadListener.splice(i, 1);
	},

	_export: function(classes) {
		for(var i = 0; i < classes.length; i++)
			window[classes[i]] = this[classes[i]];
	},

    removeAllChildNodes: function(node) {
        if(node.hasChildNodes()) {
            while(node.childNodes.length > 0) {
                node.removeChild(node.firstChild);
            }
        }
    },

    ucfirst: function(mystr) {
        return mystr.substr(0, 1).toUpperCase() + mystr.substr(1).toLowerCase();
    },

    popBubble: function(e) {
        if(!e) {
            e = window.event;
            e.cancelBubble = true;
        }
        if(e.stopPropagation)
            e.stopPropagation();
    },

	applyClasses: function(parm, obj) {
		if(parm)
			for(var i = 0; i < parm.length; i++)
				obj.addClassName(parm[i]);
	},

	unapplyClasses: function(parm, obj) {
		if(parm)
			for(var i = 0; i < parm.length; i++)
				obj.removeClassName(parm[i]);
	},

	openDebugConsole: function() {
		if(SWAT._deferredConsole) {
			if($('PageTable')) {
				$('PageTable').up().insert({ top: SWAT.debugConsole });
				SWAT._deferredConsole = false;
			}
			return;
		}
		if(SWAT.debugConsole || (console && console.log))
			return;
		SWAT.debugConsole = new Element('div', { style: 'border:1px solid black;overflow:auto;width:100%;height:150px;background:white;font-family:monospace;font-size:10px' });
		if(!$('PageTable'))
			SWAT._deferredConsole = true;
		else
			$('PageTable').up().insert({ top: SWAT.debugConsole });
	},

	closeDebugConsole: function() {
		if(!SWAT.debugConsole || (console && console.log))
			return;

		if(SWAT.debugConsole.remove)
			SWAT.debugConsole.remove();
		else
			SWAT.debugConsole.parentNode.removeChild(SWAT.debugConsole);
		delete SWAT.debugConsole;
	},

	log: function(msg) {
		if(window.console && window.console.log)
			console.log(msg);
		else {
			SWAT.openDebugConsole();
			SWAT.debugConsole.insert('-> ' + msg + '<br />');
		}
	},

	_dir_array_rec: function(arr) {
		var htm = '<ul>';
		for(var i = 0; i < arr.length; i++)
			htm += '<li><b>' + i + '</b>: ' + Object.inspect(arr[i]) + SWAT._dir_rec(arr[i]) + '</li>';
		htm += '</ul>';
		return htm;
	},

	_dir_rec: function(obj, depth) {
		var htm = '<ul>';
		var cnt = 0;
		for(var id in obj) {
			if(Object.isFunction(obj[id]))
				continue;
			cnt++;
			htm += '<li><b>' + id + '</b>: ' + Object.inspect(obj[id]);
			if(!obj[id])
				htm += '';
			else if(Object.inspect(obj[id]) == '[object Object]' || Object.isHash(obj[id]))
				htm += SWAT._dir_rec(obj[id], depth+1);
			else if(Object.isArray(obj[id]))
				htm += SWAT._dir_array_rec(obj[id]);
			htm += '</li>';
		}
		htm += '</ul>';
		if(cnt == 0)
			return '';
		else
			return htm;
	},

	dir: function(obj) {
		if(window.console && window.console.dir)
			console.dir(obj);
		else {
			var htm = SWAT._dir_rec(obj, 0);
			SWAT.log(htm);
		}
	},

	time: function(nm) {
		if(window.console && window.console.time)
			console.time(nm);
	},

	timeEnd: function(nm) {
		if(window.console && window.console.timeEnd)
			console.timeEnd(nm);
	},

	incCount: function(className) {
		if(!SWAT._classCounts[className])
			SWAT._classCounts[className] = 1;
		else
			SWAT._classCounts[className]++;
	},

	dumpClassStats: function() {
		for(var id in SWAT._classCounts)
			SWAT.log(id + ': ' + SWAT._classCounts[id]);
		var elts = [ 'span', 'div', 'ul', 'li', 'button', 'a', 'b', 'i', 'u' ];
		for(var i = 0; i < elts.length; i++)
			SWAT.log(elts[i] + ': ' + $$(elts[i]).length);
	}
};

function ExportClasses() {
	SWAT._export.bind(this)(arguments);
}
