orion.Framework = function () {
	this._installOrderBundles = [];
	this._resolveOrderBundles = [];
	this._exports = {};
	this._requiredBundles = {};
	this._properties = {};
	this._currentBundleId = 0;
};

orion.Framework.prototype = {
	getBundles : function() {
		return this._installOrderBundles.slice();
	},
	getProperty : function(name) {
		return this._properties[name];
	},
	setProperty : function(name, value) {
		this._properties[name] = value;
	},
	installBundle : function(location, headers) {
		if (location === undefined)
			throw "location cannot be undefined";
		
		if (location === null)
			throw "location cannot be null";

		var bundleData = new orion.BundleData(this._currentBundleId, location, headers);
		var bundle = new orion.Bundle(this, bundleData);

		for ( var i = 0; i < this._installOrderBundles.length; i++) {
			if (bundle.equals(this._installOrderBundles[i]))
				return this._installOrderBundles[i];
		}
		this._installOrderBundles[this._currentBundleId] = bundle;
		this._currentBundleId++;

		return bundle;
	},
	refresh : function() {
		var uninstalledBundleFound = false;
		var resolvedBundles = this._resolveOrderBundles.slice();
		var i = 0;
		var bundle = null;
		
		var newInstallOrderBundles = [];
		for (i = 0; i < this._installOrderBundles.length; i++) {
			bundle = this._installOrderBundles[i];
			if (bundle.getState() !== orion.Bundle.UNINSTALLED) {
				newInstallOrderBundles.push(bundle);
			}
		}
		this._installOrderBundles = newInstallOrderBundles;
		
		for (i = 0; i < resolvedBundles.length; i++) {
			bundle = resolvedBundles[i];
			if (bundle.getState() === orion.Bundle.UNINSTALLED) {
				uninstalledBundleFound = true;
			}

			if (uninstalledBundleFound) {
				this._unresolveBundle(bundle);
			}
		}
		if (uninstalledBundleFound) {
			var newResolveOrderBundles = [];
			for (i = 0; i < this._resolveOrderBundles.length; i++) {
				bundle = this._resolveOrderBundles[i];
				if (bundle.getState() === orion.Bundle.RESOLVED || bundle.getState() === orion.Bundle.ACTIVE) {
					newResolveOrderBundles.push(bundle);
				}
			}
			this._resolveOrderBundles = newResolveOrderBundles;

			this.resolve();
		}
	},
	resolve : function() {
		var unresolvedBundles = [];
		var i = 0;
		for (i = 0; i < this._installOrderBundles.length; i++) {
			var bundle = this._installOrderBundles[i];
			if (bundle.getState() === orion.Bundle.INSTALLED)
				unresolvedBundles.push(bundle);
		}

		var resolvedBundles = [];
		var resolvedBundle = null;
		while (unresolvedBundles.length !== 0) {
			resolvedBundle = this._stepResolver(unresolvedBundles);
			if (resolvedBundle !== null)
				resolvedBundles.push(resolvedBundle);
			else
				break;
		}
	},
	shutdown : function() {
		var reversed = this._installOrderBundles.slice().reverse();
		for ( var i = 0; i < reversed.length; i++) {
			var bundle = reversed[i];
			bundle.uninstall();
		}
		this.refresh();
	},
	_getBundleContext : function(bundle) {
		return new orion.BundleContext(bundle, this);
	},
	_stepResolver : function(unresolvedBundles) {
		for (var i = 0; i < unresolvedBundles.length; i++) {
			var bundle = unresolvedBundles[i];
			if (this._resolveBundle(bundle)) {
				this._resolveOrderBundles.push(bundle);
				unresolvedBundles.splice(i,1);
				return bundle;
			}
		}
		return null;
	},
	_resolveBundle: function(bundle) {
		if (bundle._isSingleton() && this._requiredBundles[bundle.getName()])
			return false;

		if (this._wire(bundle)) {
			bundle._resolve();
			this._addExports(bundle);
			this._addRequiredBundle(bundle);
			return true;
		}
		this._unwire(bundle);
		return false;
	},
	_wire : function(bundle) {
		var imports = bundle._getImports();
		for (var i = 0; i < imports.length; i++) {
			var jsImport = imports[i];
			var name = jsImport.getName();
			var candidates = this._exports[name];
			var satisfied = false;
			if (candidates) {
				for (var j = 0; j < candidates.length; j++) {
					var candidate = candidates[j];
					satisfied = jsImport.wire(candidate);
					if (satisfied)
						break;
				}
			}
			if (!satisfied && !jsImport.isOptional())
				return false;
		}
		return true;
	},
	_addExports : function(bundle) {
		var exports = bundle._getExports();
		for (var i = 0; i < exports.length; i++) {
			var jsExport = exports[i];
			var name = jsExport.getName();
			var namedExports = this._exports[name];
			if (!namedExports) {
				namedExports = [];
				this._exports[name] = namedExports;
			}
			namedExports.push(jsExport);
			namedExports.sort(orion.Framework._exportsComparator);
		}
	},
	_addRequiredBundle : function(bundle) {
		var name = bundle.getName();
		var namedBundles = this._requiredBundles[name];
		if (! namedBundles) {
			namedBundles = [];
			this._requiredBundles[name]= namedBundles;
		}
		namedBundles.push(bundle);
		namedBundles.sort(orion.Framework._requireBundlesComparator);
	},
	_unresolveBundle : function(bundle) {
		this._removeExports(bundle);
		this._removeRequiredBunde(bundle);
		bundle._unresolve();
		this._unwire(bundle);
	},
	_removeExports : function(bundle) {
		var exports = bundle._getExports();
		for ( var i = 0; i < exports.length; i++) {
			var jsExport = exports[i];
			var name = jsExport.getName();
			var namedExports = this._exports[name];
			if (!namedExports)
				continue;

			for ( var j = 0; j < namedExports.length; j++) {
				if (namedExports[j] === jsExport) {
					namedExports.splice(j, 1);
					break;
				}
			}
			if (namedExports.length === 0)
				delete this._exports[name];
		}
	},
	_removeRequiredBunde : function(bundle) {
		var name = bundle.getName();
		var namedBundles = this._requiredBundles[name];
		if (!namedBundles)
			return;

		for ( var i = 0; i < namedBundles.length; i++) {
			if (namedBundles[i] === bundle) {
				namedBundles.splice(i, 1);
				break;
			}
		}
		if (namedBundles.length === 0)
			delete this._requiredBundles[name];
	},
	_unwire : function(bundle) {
		var imports = bundle._getImports();
		for ( var i = 0; i < imports.length; i++) {
			var jsImport = imports[i];
			jsImport.unwire();
		}
	}
};

orion.Framework._exportsComparator = function(export0, export1) {
	// order switched for descending order
	var result = export1.getVersion().compareTo(export0.getVersion());
	if (result == 0)
		result = export0.getBundleId() - export1.getBundleId();

	return result;
};

orion.Framework._requireBundlesComparator = function(bundle0, bundle1) {
	// order switched for descending order
	var result = bundle1.getVersion().compareTo(bundle0.getVersion());
	if (result == 0)
		result = bundle0.getBundleId() - bundle1.getBundleId();

	return result;
};

orion.Framework._fetch = function(location){
	if (typeof XMLHttpRequest != "undefined") {
		var request = new XMLHttpRequest();
		request.open("GET", location, false);
		request.send();
		return request.responseText;
	}
	
	var url = new java.net.URL(location);	
    var reader = new java.io.InputStreamReader(url.openStream());
    var stringWriter = new java.io.StringWriter();
    var buffer = java.lang.reflect.Array.newInstance(java.lang.Character.TYPE, 1024);    
    var charsRead;
	
	try { 
	    while ((charsRead = reader.read(buffer, 0, 1024)) != -1) {
	    	stringWriter.write(buffer, 0, charsRead);
	    }
	} finally {
		reader.close;
		stringWriter.close();
	}
	return stringWriter.toString();		
};

orion.Framework._eval = function(script){
	// done to give global scope when evaling
	return eval(script);
};





