package at.renehollander.duktape.values;

import at.renehollander.duktape.Destroyable;
import at.renehollander.duktape.Duktape;
import at.renehollander.duktape.Function;

import java.lang.reflect.Method;

public class DukJavaFunction implements Destroyable {

    private Duktape duktape;
    private Method method;
    private Object object;

    private DukFunction dukFunction;

    public DukJavaFunction(Duktape duktape, Method method, Object object) {
        this.duktape = duktape;
        this.method = method;
        this.object = object;
    }

    public DukJavaFunction(Duktape duktape, Function function) {
        this.duktape = duktape;
        this.method = function.getClass().getMethods()[0];
        this.object = function;
    }

    public Duktape getDuktape() {
        return duktape;
    }

    public Object getObject() {
        return object;
    }

    public Method getMethod() {
        return method;
    }

    public DukFunction getDukFunction() {
        if (dukFunction == null) {
            this.dukFunction = new DukFunction(this.getDuktape(), _createAndReference(this.getDuktape().getContextPointer(), this.getMethod(), this.getMethod().getParameterCount(), this.getObject(), this.getMethod().getReturnType().equals(Void.TYPE)));
        }
        return this.dukFunction;
    }

    @Override
    public void destroy() throws Throwable {
        if (dukFunction != null) {
            this.dukFunction.destroy();
        }
    }

    @Override
    public boolean equals(Object o) {
        // TODO implement
        throw new UnsupportedOperationException("not yet implemented");
    }

    @Override
    public int hashCode() {
        // TODO implement
        throw new UnsupportedOperationException("not yet implemented");
    }

    private static native int _createAndReference(long contextPointer, Method method, int paramCount, Object object, boolean voidFunction);

}

@@ -196,16 +196,41 @@
 .Method;
+%0Aimport java.util.Arrays;
 %0A%0Apublic
@@ -694,16 +694,31 @@
 ethod = 
+validateMethod(
 function
@@ -744,16 +744,17 @@
 ods()%5B0%5D
+)
 ;%0A      
@@ -1951,10 +1951,601 @@
 tion);%0A%0A
+    public static Method validateMethod(Method method) %7B%0A        if (!method.getReturnType().equals(Void.TYPE) && !method.getReturnType().equals(DukValue.class)) %7B%0A            throw new IllegalArgumentException(%22Method %22 + method + %22 must have either a void or DukValue return type%22);%0A        %7D%0A        Arrays.stream(method.getParameterTypes()).forEach((clazz) -%3E %7B%0A            if (!clazz.equals(DukValue.class)) %7B%0A                throw new IllegalArgumentException(%22Method %22 + method + %22 must only have DukValue as parameter types%22);%0A            %7D%0A        %7D);%0A        return method;%0A    %7D%0A%0A
 %7D%0A

validate method passed to DukJavaFunction to avoid crashes