package com.hammurapi.common;

import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;

import javax.script.AbstractScriptEngine;
import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.script.SimpleBindings;

import com.hammurapi.common.TokenExpander.TokenSource;

public class TokenExpanderScriptEngine extends AbstractScriptEngine {

	private ScriptEngineFactory factory;
	private ScriptEngine javaEngine;

	public TokenExpanderScriptEngine() {
		this(null);
	}

	public TokenExpanderScriptEngine(ScriptEngineFactory factory) {
		this.factory = factory;
		javaEngine = new ScriptEngineManager(TokenExpanderScriptEngine.class.getClassLoader()).getEngineByExtension("java");
		
	}

	public Object eval(String script, final ScriptContext scriptContext) throws ScriptException {
		TokenExpander te = new TokenExpander(new TokenSource() {

			@Override
			public String getToken(String name) {
				try {
					return evalToken(scriptContext, name);
				} catch (ScriptException e) {
					throw new TokenExpansionException(e);
				}
			}
			
		});
		return te.expand(script);
	}

	protected String evalToken(ScriptContext scriptContext, String name) throws ScriptException {
		Object ret;
		if (javaEngine==null || name.indexOf('.')==-1) {
			ret = scriptContext.getAttribute(name);
		} else {		
			ret = javaEngine.eval("return "+name+";", scriptContext);
		}
		return ret==null ? null : ret.toString();
	}

	public Object eval(Reader reader, ScriptContext scriptContext) throws ScriptException {
		StringWriter sw = new StringWriter();
		char[] buf = new char[4096];
		int l;
		try {
			while ((l=reader.read(buf))!=-1) {
				sw.write(buf, 0, l);
			}
			sw.close();
		} catch (IOException e) {
			throw new ScriptException(e);
		}
		return eval(sw.toString(), scriptContext);
	}

	public Bindings createBindings() {
		return new SimpleBindings();
	}

	public ScriptEngineFactory getFactory() {
		if (factory == null) {
			factory = new TokenExpanderScriptEngineFactory();
		}
		return factory;
	}


}
