package nashorn.with.problem;

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

/** 
 *
 * @author Jaroslav Tulach
 */
public class NashornIdProblem {

    public static void main(String[] args) throws Exception {
        ScriptEngineManager sem = new ScriptEngineManager();
        ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
        Invocable inv = (Invocable) eng;

        // oK
        testIdentity(eng, new Object());
        
        // ok
        Object jsObj = eng.eval("new Object()");
        testIdentity(eng, jsObj);
        
        // fails on JDK8b132
        defineArraySizeFn(eng);
        Object[] arr = (Object[]) checkArray(inv, eng.eval("[ new Object() ]"));
        testIdentity(eng, arr[0]);
    }
    
    private static void testIdentity(ScriptEngine eng, Object obj) throws Exception {
        Invocable inv = (Invocable) eng;

        eng.eval("function id(x) { return x; }");
        
        Object returned = inv.invokeFunction("id", obj);
        
        if (returned == obj || obj.equals(returned)) {
            return;
        }
        throw new IllegalStateException("Not equals! obj: " + obj + " returned: " + returned + "\ntypes: " + obj.getClass() + " real: " + returned.getClass());
    }
    
    static Object checkArray(Invocable inv, Object val) throws Exception {
        final Object fnRes = inv.invokeFunction("toJavaArray", val, null);
        int length = ((Number) fnRes).intValue();
        if (length == -1) {
            return val;
        }
        Object[] arr = new Object[length];
        inv.invokeFunction("toJavaArray", val, arr);
        return arr;
    }
    static void defineArraySizeFn(ScriptEngine eng) throws ScriptException {
        eng.eval("function toJavaArray(arr, to) {\n"
            + "if (to === null) {\n"
            + "  if (Object.prototype.toString.call(arr) === '[object Array]') return arr.length;\n"
            + "  else return -1;\n"
            + "} else {\n"
            + "  var l = arr.length;\n"
            + "  for (var i = 0; i < l; i++) to[i] = arr[i];\n"
            + "  return l;\n"
            + "}"
            + "}"
        );
    }
    
}
