/*
 *   Copyright 2005 The Apache Software Foundation
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 */
package org.apache.felix.mishell;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import javax.script.SimpleBindings;

import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;

/**
 * This class acts as a delegate for all the available ScriptEngineManagers. Unluckily, the standard did not
 * define it as an interface, so we need to extend it to allow polymorphism. However, no calls to super are used.
 * It wraps all available ScriptEngineManagers in the OSGi ServicePlatform into a merged ScriptEngineManager.
 * 
 * Internally, what this class does is creating ScriptEngineManagers for each bundle 
 * that contains a ScriptEngineFactory and includes a META-INF/services/javax.script.ScriptEngineFactory file. 
 * It assumes that the file contains a list of @link ScriptEngineFactory classes. For each bundle, it creates a
 * ScriptEngineManager, then merges them. @link ScriptEngineFactory objects are wrapped
 * into @link OSGiScriptEngineFactory objects to deal with problems of context class loader:
 * Those scripting engines that rely on the ContextClassloader for finding resources need to use this wrapper
 * and the @link OSGiScriptFactory. Mainly, jruby does.
 * 
 * Note that even if no context classloader issues arose, it would still be needed to search manually for the 
 * factories and either use them directly (losing the mimeType/extension/shortName mechanisms for finding engines
 * or manually registering them) or still use this class, which would be smarter. In the latter case, 
 * it would only be needed to remove the hack that temporarily sets the context classloader to the appropriate, 
 * bundle-related, class loader.
 * 
 * Caveats:
 * <ul><li>
 * All factories are wrapped with an {@link OSGiScriptEngineFactory}. As Engines are not wrapped,
 * calls like 
 * <code>
 * ScriptEngineManager osgiManager=new OSGiScriptEngineManager(context);<br>
 * ScriptEngine engine=osgiManager.getEngineByName("ruby");
 * ScriptEngineFactory factory=engine.getFactory() //this does not return the OSGiFactory wrapper
 * factory.getScriptEngine(); //this might fail, as it does not use OSGiScriptEngineFactory wrapper
 * </code>
 * might result in unexpected errors. Future versions may wrap the ScriptEngine with a OSGiScriptEngine to solve this
 * issue, but for the moment it is not needed.
 * </li>
 * 
 */
public class OSGiScriptEngineManager extends ScriptEngineManager{
	private Bindings bindings;
	private Map <ScriptEngineManager, ClassLoader> classLoaders;
	private BundleContext context;
	
	public OSGiScriptEngineManager(BundleContext context){
		this.context=context;
		bindings=new SimpleBindings();
		this.classLoaders=findManagers(context);
	}
	/**
	 * This method is the only one that is visible and not part of the ScriptEngineManager class.
	 * Its purpose is to find new managers that weren't available before, but keeping the globalScope bindings
	 * set.
	 * If you want to clean the bindings you can either get a fresh instance of OSGiScriptManager or
	 * setting up a new bindings object.
	 * This can be done with:
	 * <code>
	 * ScriptEngineManager manager=new OSGiScriptEngineManager(context);
	 * (...)//do stuff
	 * osgiManager=(OSGiScriptEngineManager)manager;//cast to ease reading
	 * osgiManager.reloadManagers();
	 * 
	 * manager.setBindings(new OSGiBindings());//or you can use your own bindings implementation
	 * 
	 * </code>   
	 *
	 */
	public void reloadManagers(){
		this.classLoaders=findManagers(context);
	}
	
	public Object get(String key) {
		return bindings.get(key);
	}

	public Bindings getBindings() {
		return bindings;
	}

	public ScriptEngine getEngineByExtension(String extension) {
		//TODO this is a hack to deal with context class loader issues
		ScriptEngine engine=null;
		for(ScriptEngineManager manager: classLoaders.keySet()){
			ClassLoader old=Thread.currentThread().getContextClassLoader();
			Thread.currentThread().setContextClassLoader(classLoaders.get(manager));
			engine=manager.getEngineByExtension(extension);
			Thread.currentThread().setContextClassLoader(old);
			if (engine!=null) break;
		}
 		return engine;
	}

	public ScriptEngine getEngineByMimeType(String mimeType) {
		//TODO this is a hack to deal with context class loader issues
		ScriptEngine engine=null;
		for(ScriptEngineManager manager: classLoaders.keySet()){
			ClassLoader old=Thread.currentThread().getContextClassLoader();
			Thread.currentThread().setContextClassLoader(classLoaders.get(manager));
			engine=manager.getEngineByMimeType(mimeType);
			Thread.currentThread().setContextClassLoader(old);
			if (engine!=null) break;
		}
 		return engine;
	}

	public ScriptEngine getEngineByName(String shortName) {
		//TODO this is a hack to deal with context class loader issues
		for(ScriptEngineManager manager: classLoaders.keySet()){
			ClassLoader old=Thread.currentThread().getContextClassLoader();
			Thread.currentThread().setContextClassLoader(classLoaders.get(manager));
			ScriptEngine engine=manager.getEngineByName(shortName);
			Thread.currentThread().setContextClassLoader(old);
			if (engine!=null){
				return new OSGiScriptEngine(engine, new OSGiScriptEngineFactory(engine.getFactory(), classLoaders.get(manager)));
			}
		}
		return null;
	}
	public List<ScriptEngineFactory> getEngineFactories() {
		List<ScriptEngineFactory> osgiFactories=new ArrayList<ScriptEngineFactory>();
		for(ScriptEngineManager engineManager: classLoaders.keySet()){
			for (ScriptEngineFactory factory : engineManager.getEngineFactories()){
				osgiFactories.add(new OSGiScriptEngineFactory(factory, classLoaders.get(engineManager)));
		}
		}
		return osgiFactories;
	}

	public void put(String key, Object value) {
		bindings.put(key, value);
	}

	public void registerEngineExtension(String extension, ScriptEngineFactory factory) {
		for(ScriptEngineManager engineManager: classLoaders.keySet())
			engineManager.registerEngineExtension(extension, factory);
	}

	public void registerEngineMimeType(String type, ScriptEngineFactory factory) {
		for(ScriptEngineManager engineManager: classLoaders.keySet())
		engineManager.registerEngineMimeType(type, factory);
	}

	public void registerEngineName(String name, ScriptEngineFactory factory) {
		for(ScriptEngineManager engineManager: classLoaders.keySet())
			engineManager.registerEngineName(name, factory);
	}
	/**
	 * Follows the same behavior of @link javax.script.ScriptEngineManager#setBindings(Bindings)
	 * This means that the same bindings are applied to all the underlying managers.
	 * @param bindings
	 */
	public void setBindings(Bindings bindings) {
		this.bindings=bindings;
		for(ScriptEngineManager manager: classLoaders.keySet()){
			manager.setBindings(bindings);
		}

	}


	private Map<ScriptEngineManager, ClassLoader> findManagers(BundleContext context) {
		Map<ScriptEngineManager, ClassLoader> managers=new HashMap<ScriptEngineManager, ClassLoader>();
		try {
			for(String factoryName: findFactoryCandidates(context)){
				//We do not really need the class, but we need the classloader 
				ClassLoader factoryLoader=Class.forName(factoryName).getClassLoader();
				ScriptEngineManager manager=new ScriptEngineManager(factoryLoader);
				manager.setBindings(bindings);
				managers.put(manager, factoryLoader);
			}
			return managers;
		} catch (IOException ioe) {
			throw new RuntimeException(ioe);
		} catch (ClassNotFoundException cnfe) {
			throw new RuntimeException(cnfe);
		}
	}
	/**
	 * Iterates through all bundles to get the available @link ScriptEngineFactory classes
	 * @return the names of the available ScriptEngineFactory classes
	 * @throws IOException
	 */
	private List<String> findFactoryCandidates(BundleContext context) throws IOException{
		Bundle[] bundles = context.getBundles();
		List<String> factoryCandidates = new ArrayList<String>();
		for (Bundle bundle : bundles) {
			System.out.println(bundle.getSymbolicName());
			if(bundle.getSymbolicName().equals("system.bundle")) continue;
			Enumeration urls = bundle.findEntries("META-INF/services",
					"javax.script.ScriptEngineFactory", false);
			if (urls == null)
				continue;
			while (urls.hasMoreElements()) {
				URL u = (URL) urls.nextElement();
				BufferedReader reader = new BufferedReader(
						new InputStreamReader(u.openStream()));
				String line;
				while ((line = reader.readLine()) != null) {
					factoryCandidates.add(line.trim());
		}
			}
		}
		return factoryCandidates;
	}
}
