if (!window.Loader) 
{

var EmailValidatorRegex = /^([a-zA-Z0-9_\.\-\+])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;

Loader = {
	_loaded: [ "com.sightworks.platform.plugin" ],
	_loading: { },
	
	isLoaded: function(plugin) {
		return this._loaded.indexOf(plugin) != -1;
	},

	_handleManifest: function(pluginId, manifest) {
		var dependCount = 0;
		var loadedCount = 0;
		console.log(manifest);
		for (var i in manifest.depends) dependCount++;
		
		for (var i in manifest.depends) {
			Loader.loadPlugin(i, function() {
				loadedCount++;
				
				if (loadedCount == dependCount) {
					Loader._handleResources(pluginId, manifest);
				}
			});
		}
		
		if (dependCount == 0)
			Loader._handleResources(pluginId, manifest);
	},
	
	_handleResources: function(pluginId, info) {
		var resourceCount = 0;
		var loadedCount = 0;
		for (var i in info.manifest) {
			if (info.manifest[i].type == 'client-javascript' || info.manifest[i].type == 'client-stylesheet')
				resourceCount++;
		}
		var toLoad = [];
				
		for (var i in info.manifest) {
			if (info.manifest[i].type == 'client-javascript') {
				(function(i) {
					toLoad.push(function() {
						Loader._loadScript(pluginId, i, function() {
							var next = toLoad.shift();
							if (next)
								next();
							else
								Loader._loadedPlugin(pluginId);
						});
					});
				})(i);
			} else if (info.manifest[i].type == 'client-stylesheet') {
				(function(i) {
					toLoad.push(function() {
						Loader._loadStyles(pluginId, i, function() {
							var next = toLoad.shift();
							if (next)
								next();
							else
								Loader._loadedPlugin(pluginId);
						});
					});
				})(i);
			}
		}
		if (!toLoad.length) {
			Loader._loadedPlugin(pluginId);
		} else {
			var item = toLoad.shift();
			item();
		}
	},
	
	_loadScript: function(pluginId, script, callback) {
		if ($("script[src='/admin/plugins/" + pluginId + "/" + script + "']").size()) {
			callback();
			return;
		}
		if ($("script[data-ajax-src='/admin/plugins/" + pluginId + "/" + script + "']").size()) {
			callback();
			return;
		}
		
		var e = document.createElement('script');
		e.setAttribute('type', 'text/javascript');
		e.setAttribute('src', '/admin/plugins/' + pluginId + '/' + script);
		e.onload = function() {
			callback();
		}
		$('head')[0].appendChild(e);
		
		/*
		$.get("/admin/plugins/" + pluginId + "/" + script + '?_=' + new Date().getTime(), function(r) {
			var d = document.createElement('script');
			d.setAttribute('type', 'text/javascript');
			d.setAttribute('data-ajax-src', '/admin/plugins/' + pluginId + '/' + script);
			d.appendChild(document.createTextNode(r));
			$('head')[0].appendChild(d);
			callback();
		}, 'text');
		*/
	},
	
	_loadStyles: function(pluginId, css, callback) {
		var path = '/admin/plugins/' + pluginId + '/' + css + '?_=' + new Date().getTime();
		$.get(path, function(r) {
			var d = document.createElement('link');
			d.setAttribute('type', 'text/css');
			d.setAttribute('rel', 'stylesheet');
			d.setAttribute('href', path);
			// d.appendChild(document.createTextNode(r));
			$('head')[0].appendChild(d);
			callback();
		}, 'text');
	},
	
	_loadedPlugin: function(pluginId) {
		console.log("Loaded plugin: " + pluginId);
		this._loaded.push(pluginId);
		while (this._loading[pluginId].length) {
			var cb = this._loading[pluginId].shift();
			try {
				cb();
			} catch (e) {
				console.log(e);
			}
		}
	},
	
	// Loader.loadPlugin:
	// Load the named plugin. When it is finished loading, invoke callback.
	//  pluginId: string
	//  callback: function
	loadPlugin: function(pluginId, callback) {
		if (!callback)
			callback = function() { ; }
			
		var manifest = null;
		if (typeof pluginId == 'object')
		{
			manifest = pluginId;
			pluginId = manifest.id;
		}
		console.log("loadPlugin: " + pluginId);
			
		if (this.isLoaded(pluginId)) {
			callback();
			return;
		}
		
		if (!this._loading[pluginId]) {	
			if (manifest) {
				setTimeout(function() {
					Loader._handleManifest(pluginId, manifest);
				}, 1);
			} else {
				$.get("/admin/plugins/" + pluginId + "/Info.json?_=" + new Date().getTime(), function(info) {
					Loader._handleManifest(pluginId, info);
				}, 'json');
			}
			this._loading[pluginId] = [];
		}
		this._loading[pluginId].push(callback);
	},
	
	// Loader.getPluginsWithType
	// Loader.getPluginsWithFeature
	// Retrieve a list of plugins that conform to the specified type or feature
	// The former function checks the "type" key in Info.json; the latter checks the "provides" key.
	_getPluginsWithType: function(typeId, callback) {
		this.getPluginsWithType = this._getPluginsWithType;
		if (!callback) callback = function() { ; }
		ClientAPI.get("com.sightworks.platform.plugin", "type/" + typeId).getValue(function(r) {
			callback(r);
		});
	},
			
	getPluginsWithType: function(typeId, callback) {
		// If it's already been loaded, directly invoke the callback. Of course, _getPluginsWithType and _getPluginsWithFeature
		// replace this hook when they get invoked.
		this.loadPlugin("com.sightworks.platform.plugin.ClientAPI", function() {
			Loader._getPluginsWithType(typeId, callback);
		});
	},
	
	_getPluginsWithFeature: function(featureId, callback) {
		this.getPluginsWithFeature = this._getPluginsWithFeature;
		if (!callback) callback = function() { ; }
		ClientAPI.get("com.sightworks.platform.plugin", "feature/" + featureId).getValue(function(r) {
			callback(r);
		});
	},
	
	getPluginsWithFeature: function(featureId, callback) {
		this.loadPlugin('com.sightworks.platform.plugin.ClientAPI', function(r) {
			Loader._getPluginsWithFeature(featureId, callback);
		});
	}
};

}

