/*
 * Galatea Dialog Manager:
 * (c)2003-2004 Takuya NISHIMOTO (nishi@hil.t.u-tokyo.ac.jp)
 *
 * $Id: ECMAScript.java,v 1.12 2008/02/14 06:12:25 nishi Exp $
 *
 * Simple wrappar class for Mozilla Rhino JavaScript Engine
 */

package galatea.scripting;

import galatea.dialog.RuntimeError;
import galatea.util.Property;

import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.tools.shell.Global;

public class ECMAScript {
	private boolean useMozillaRhino_ = Property.getAsBoolean("UseMozillaRhino", false); // false;
	
	// for mozilla rhino
	private Context context_ = null;
	private Scriptable scope_ = null;
	// for java6
	private ScriptEngine engine_ = null;
	
	public ECMAScript() throws RuntimeError
	{
		if (useMozillaRhino_) {
			makeRhinoInstance();
		} else {
			makeJavaScriptInstance();
		}
	}

	public void makeJavaScriptInstance() throws RuntimeError {
		ScriptEngineManager manager = new ScriptEngineManager();
		engine_ = manager.getEngineByName("ECMAScript");
		engine_.put("Tools", new ScriptingTools());
	}

	public void makeRhinoInstance() throws RuntimeError {
		try {
			context_ = Context.enter();
			scope_ = context_.initStandardObjects(null);
			
			Global global = new Global(context_);
			scope_.put("Shell", scope_, global);
			
			ScriptingTools tools = new ScriptingTools();
			scope_.put("Tools", scope_, tools);
			
		} catch (Exception e) {
			throw new RuntimeError(e.getMessage());
		}
	}
	
	public String evaluate(String script) throws RuntimeError
	{
		if (useMozillaRhino_) {
			return evaluateMozillaRhino(script);
		} else {
			return evaluateJavaScript(script);
		}
	}
	
	private String evaluateJavaScript(String script) throws RuntimeError {
		String str = "error";
		try {
			str = engine_.eval(script).toString();
		} catch (Exception e) {
			throw new RuntimeError(e.getMessage() + "\n"
					+ script);
		}
		return str;
	}

	public String evaluateMozillaRhino(String script) throws RuntimeError {
		if ( context_ == null )
			return "context_error";
		if ( scope_ == null )
			return "scope_error";
		if ( script == null )
			return "error";
		String str = "error";
		Object result = null;
		try {
			result = context_.evaluateString(scope_, script, "GalateaDialogManager", 1, null);
			// str = context_.toString(result);
			str = result.toString();
		} catch (Exception e) {
			throw new RuntimeError(e.getMessage() + "\n"
					+ script);
		}
		return str;
	}
	
	public String getVersionAndCopyright() {
		if (useMozillaRhino_) {
			return "Uses Mozilla Rhino from mozilla.org.\n"
			+ "See http://www.mozilla.org/rhino/.\n"
			+ context_.getImplementationVersion() + "\n";
		} else {
			return "Uses javax.script for ECMAScript engine.\n"; 
		}
	}
	
	public static void main(String args[]) throws Exception 
	{
		ECMAScript sc = new ECMAScript(); // ECMAScript.getInstance();
		String r = "";
		/*
		 r = sc.evaluate("o = {a:1, b:['x','y']}"); System.err.println(r);
		 r = sc.evaluate("o.b[0]"); System.err.println(r);
		 r = sc.evaluate("p = {a:1}"); System.err.println(r);
		 r = sc.evaluate("p.b = 2"); System.err.println(r);
		 r = sc.evaluate("1+1"); System.err.println(r);
		 r = sc.evaluate("p"); System.err.println(r);
		 */
		/*
		 r = sc.evaluate("var when = new Object();"); System.err.println(r);
		 r = sc.evaluate("var dialog = new Object();"); System.err.println(r);
		 r = sc.evaluate("dialog.when = when;"); System.err.println(r);
		 r = sc.evaluate("dialog.when.value = 20;"); System.err.println(r);
		 r = sc.evaluate("when.value;"); System.err.println(r);
		 */
		String s ="weather = new Object();"
			+"weather.initial1 = undefined;"
			+"weather.place  = undefined;"
			+"weather.when   = undefined;"
			+"weather.block2 = undefined;"
			+"weather.initial1$ = new Object();"
			+"weather.initial1$.promptcount = 1;"
			+"weather.place$ = new Object();"
			+"weather.place$.promptcount = 1;"
			+"weather.place$.justfilled = false;"
			+"weather.when$ = new Object();"
			+"weather.when$.promptcount = 1;"
			+"weather.when$.justfilled = false;"
			+"weather.nextitem$ = 'hello';";
		
		r = sc.evaluate(s); System.err.println(r);
		
		s = "with(weather){ nextitem$ }";
		r = sc.evaluate(s); System.err.println(r);
		
		s = "with(weather){ 'hoge' }";
		r = sc.evaluate(s); System.err.println(r);
		
		//r = sc.objectToString("o"); System.err.println(r);
		
		//sc.exit();
	}
}

