/*
 * Copyright 2008 Google Inc.
 *
 * 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 com.google.gwt.dev.shell.rewrite;

import com.google.gwt.dev.shell.JavaScriptHost;
import com.google.gwt.dev.util.Name.InternalName;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.Method;

import java.lang.reflect.Modifier;
import java.util.Locale;
import java.util.Map;

/**
 * Turns native method declarations into normal Java functions which perform the
 * corresponding JSNI dispatch.
 */
public class RewriteJsniMethods extends ClassVisitor {

  /**
   * Fast way to look up boxing methods.
   */
  private static class Boxing {

    /**
     * A matching list of boxed types for each primitive type.
     */
    private static final Type[] BOXED_TYPES = new Type[] {
        VOID_TYPE, BOOLEAN_TYPE, CHARACTER_TYPE, BYTE_TYPE, SHORT_TYPE,
        INTEGER_TYPE, FLOAT_TYPE, LONG_TYPE, DOUBLE_TYPE,};

    /**
     * The list of primitive types.
     */
    private static final Type[] PRIMITIVE_TYPES = new Type[] {
        Type.VOID_TYPE, Type.BOOLEAN_TYPE, Type.CHAR_TYPE, Type.BYTE_TYPE,
        Type.SHORT_TYPE, Type.INT_TYPE, Type.FLOAT_TYPE, Type.LONG_TYPE,
        Type.DOUBLE_TYPE,};

    /**
     * A map of Type.sort() to valueOf Method. There are 11 possible results
     * from Type.sort(), 0 through 10.
     */
    private static final Method[] SORT_MAP = new Method[11];

    static {
      assert PRIMITIVE_TYPES.length == BOXED_TYPES.length;
      for (int i = 0; i < PRIMITIVE_TYPES.length; ++i) {
        Type primitive = PRIMITIVE_TYPES[i];
        Type boxed = BOXED_TYPES[i];
        if (boxed != null) {
          SORT_MAP[i] = new Method("valueOf", boxed, new Type[] {primitive});
        }
      }
    }

    public static Method getBoxMethod(Type type) {
      int sortType = type.getSort();
      assert (sortType >= 0 && sortType < SORT_MAP.length) : "Unexpected JavaScriptHostInfo.get index - "
          + sortType;
      return SORT_MAP[sortType];
    }
  }

  /**
   * Oracle for info regarding {@link JavaScriptHost}.
   */
  private static class JavaScriptHostInfo {

    /**
     * The {@link JavaScriptHost} type.
     */
    public static final Type TYPE = Type.getType(JavaScriptHost.class);

    /**
     * The parameter signature of {@link JavaScriptHost}'s invoke* methods, in
     * classes.
     */
    private static final Class<?>[] INVOKE_NATIVE_PARAM_CLASSES = new Class[] {
        String.class, Object.class, Class[].class, Object[].class,};

    /**
     * The parameter signature of {@link JavaScriptHost}'s invoke* methods, in
     * types.
     */
    private static final Type[] INVOKE_NATIVE_PARAM_TYPES;

    /**
     * A map of Type.sort() to JavaScriptHostInfo.
     */
    private static final JavaScriptHostInfo[] SORT_MAP = new JavaScriptHostInfo[11];

    static {
      INVOKE_NATIVE_PARAM_TYPES = new Type[INVOKE_NATIVE_PARAM_CLASSES.length];
      for (int i = 0; i < INVOKE_NATIVE_PARAM_TYPES.length; ++i) {
        INVOKE_NATIVE_PARAM_TYPES[i] = Type.getType(INVOKE_NATIVE_PARAM_CLASSES[i]);
      }

      Class<?>[] primitives = {
          void.class, boolean.class, byte.class, char.class, short.class,
          int.class, long.class, float.class, double.class};
      for (Class<?> c : primitives) {
        Type type = Type.getType(c);
        String typeName = type.getClassName();
        String firstChar = typeName.substring(0, 1).toUpperCase(Locale.ROOT);
        typeName = firstChar + typeName.substring(1);
        SORT_MAP[type.getSort()] = new JavaScriptHostInfo(type, "invokeNative"
            + typeName);
      }
      JavaScriptHostInfo objectType = new JavaScriptHostInfo(
          Type.getType(Object.class), "invokeNativeObject", true);
      SORT_MAP[Type.ARRAY] = objectType;
      SORT_MAP[Type.OBJECT] = objectType;
      assert noNulls(SORT_MAP) : "Did not fully fill in JavaScriptHostInfo.SORT_MAP";
    }

    public static JavaScriptHostInfo get(int sortType) {
      assert (sortType >= 0 && sortType < SORT_MAP.length) : "Unexpected JavaScriptHostInfo.get index - "
          + sortType;
      return SORT_MAP[sortType];
    }

    /**
     * Validate our model against the real JavaScriptHost class.
     */
    private static boolean matchesRealMethod(String methodName, Type returnType) {
      try {
        java.lang.reflect.Method method = JavaScriptHost.class.getDeclaredMethod(
            methodName, INVOKE_NATIVE_PARAM_CLASSES);
        assert (method.getModifiers() & Modifier.STATIC) != 0 : "Was expecting method '"
            + method + "' to be static";
        Type realReturnType = Type.getType(method.getReturnType());
        return realReturnType.getDescriptor().equals(returnType.getDescriptor());
      } catch (SecurityException e) {
      } catch (NoSuchMethodException e) {
      }
      return false;
    }

    private static boolean noNulls(Object[] array) {
      for (Object element : array) {
        if (element == null) {
          return false;
        }
      }
      return true;
    }

    private final Method method;

    private final boolean requiresCast;

    private JavaScriptHostInfo(Type returnType, String methodName) {
      this(returnType, methodName, false);
    }

    private JavaScriptHostInfo(Type returnType, String methodName,
        boolean requiresCast) {
      this.requiresCast = requiresCast;
      this.method = new Method(methodName, returnType,
          INVOKE_NATIVE_PARAM_TYPES);
      assert matchesRealMethod(methodName, returnType) : "JavaScriptHostInfo for '"
          + this + "' does not match real method";
    }

    public Method getMethod() {
      return method;
    }

    public boolean requiresCast() {
      return requiresCast;
    }

    @Override
    public String toString() {
      return method.toString();
    }
  }

  /**
   * Rewrites native Java methods to dispatch as JSNI.
   */
  private class MyMethodAdapter extends GeneratorAdapter {

    private String descriptor;
    private boolean isStatic;
    private String name;

    public MyMethodAdapter(MethodVisitor mv, int access, String name,
        String desc) {
      super(Opcodes.ASM6, mv, access, name, desc);
      this.descriptor = desc;
      this.name = name;
      isStatic = (access & Opcodes.ACC_STATIC) != 0;
    }

    /**
     * Replacement for {@link GeneratorAdapter#box(Type)}, which always calls,
     * for example, {@code new Boolean} instead of using
     * {@link Boolean#valueOf(boolean)}.
     */
    @Override
    public void box(Type type) {
      Method method = Boxing.getBoxMethod(type);
      if (method != null) {
        invokeStatic(method.getReturnType(), method);
      }
    }

    /**
     * Does all of the work necessary to do the dispatch to the appropriate
     * variant of {@link JavaScriptHost#invokeNativeVoid
     * JavaScriptHost.invokeNative*}. And example output:
     *
     * <pre>
     * return JavaScriptHost.invokeNativeInt(
     *     "@com.google.gwt.sample.hello.client.Hello::echo(I)", null,
     *     new Class[] {int.class,}, new Object[] {x,});
     * </pre>
     */
    @Override
    public void visitCode() {
      super.visitCode();

      /*
       * If you modify the generated code, you must recompute the stack size in
       * visitEnd().
       */

      // First argument - JSNI signature
      String jsniTarget = getJsniSignature(name, descriptor);
      visitLdcInsn(jsniTarget);
      // Stack is at 1

      // Second argument - target; "null" if static, otherwise "this".
      if (isStatic) {
        visitInsn(Opcodes.ACONST_NULL);
      } else {
        loadThis();
      }
      // Stack is at 2

      // Third argument - a Class[] describing the types of this method
      loadClassArray();
      // Stack is at 3; reaches 6 internally

      // Fourth argument - all the arguments boxed into an Object[]
      loadArgArray();
      // Stack is at 4; reaches 7 or 8 internally (long/double takes 2)

      // Invoke the matching JavaScriptHost.invokeNative* method
      Type returnType = Type.getReturnType(descriptor);
      JavaScriptHostInfo info = JavaScriptHostInfo.get(returnType.getSort());
      invokeStatic(JavaScriptHostInfo.TYPE, info.getMethod());
      // Stack is at 1
      if (info.requiresCast()) {
        checkCast(returnType);
      }
      returnValue();
      // Stack is at 0
    }

    @Override
    public void visitEnd() {
      // Force code to be visited; required since this was a native method.
      visitCode();

      /*
       * For speed, we don't ask ASM to COMPUTE_MAXS. We manually calculated a
       * max depth of 8.
       *
       * Also, when tobyr tried getting ASM to compute the correct stack size,
       * ASM seemed to compute the wrong value for reasons we don't understand.
       */
      int maxStack = 8;
      int maxLocals = 0; // Computed by GeneratorAdapter superclass.
      super.visitMaxs(maxStack, maxLocals);
      super.visitEnd();
    }

    private void loadClassArray() {
      Type[] argTypes = Type.getArgumentTypes(descriptor);
      push(argTypes.length);
      newArray(CLASS_TYPE);
      // Stack is at 3
      for (int i = 0; i < argTypes.length; ++i) {
        dup();
        push(i);
        push(argTypes[i]);
        arrayStore(CLASS_TYPE);
      }
    }
  }

  private static final Type BOOLEAN_TYPE = Type.getObjectType("java/lang/Boolean");
  private static final Type BYTE_TYPE = Type.getObjectType("java/lang/Byte");
  private static final Type CHARACTER_TYPE = Type.getObjectType("java/lang/Character");
  private static final Type CLASS_TYPE = Type.getObjectType("java/lang/Class");
  private static final Type DOUBLE_TYPE = Type.getObjectType("java/lang/Double");
  private static final Type FLOAT_TYPE = Type.getObjectType("java/lang/Float");
  private static final Type INTEGER_TYPE = Type.getObjectType("java/lang/Integer");
  private static final Type LONG_TYPE = Type.getObjectType("java/lang/Long");
  private static final Type SHORT_TYPE = Type.getObjectType("java/lang/Short");
  private static final Type VOID_TYPE = Type.getObjectType("java/lang/Void");

  /**
   * The internal name of the class we're operating on.
   */
  private String classDesc;
  private Map<String, String> anonymousClassMap;

  public RewriteJsniMethods(ClassVisitor v,
      Map<String, String> anonymousClassMap) {
    super(Opcodes.ASM6, v);
    this.anonymousClassMap = anonymousClassMap;
  }

  @Override
  public void visit(final int version, final int access, final String name,
      final String signature, final String superName, final String[] interfaces) {
    this.classDesc = name;
    super.visit(version, access, name, signature, superName, interfaces);
  }

  @Override
  public MethodVisitor visitMethod(int access, String name, String desc,
      String signature, String[] exceptions) {

    boolean isNative = (access & Opcodes.ACC_NATIVE) != 0;
    access &= ~Opcodes.ACC_NATIVE;

    MethodVisitor mv = super.visitMethod(access, name, desc, signature,
        exceptions);

    if (isNative) {
      mv = new MyMethodAdapter(mv, access, name, desc);
    }

    return mv;
  }

  /**
   * Returns the JSNI signature describing the method.
   *
   * @param name the name of the method; for example {@code "echo"}
   * @param descriptor the descriptor for the method; for example {@code "(I)I"}
   * @return the JSNI signature for the method; for example, {@code
   *         "@com.google.gwt.sample.hello.client.Hello::echo(I)"}
   */
  private String getJsniSignature(String name, String descriptor) {
    int argsIndexBegin = descriptor.indexOf('(');
    int argsIndexEnd = descriptor.indexOf(')');
    assert argsIndexBegin != -1 && argsIndexEnd != -1
        && argsIndexBegin < argsIndexEnd : "Could not find the arguments in the descriptor, "
        + descriptor;
    String argsDescriptor = descriptor.substring(argsIndexBegin,
        argsIndexEnd + 1);
    String classDescriptor = InternalName.toBinaryName(classDesc);
    String newDescriptor = anonymousClassMap.get(classDesc);
    if (newDescriptor != null) {
      classDescriptor = InternalName.toBinaryName(newDescriptor);
    }
    // Always use binary names for JSNI method names
    return "@" + classDescriptor + "::" + name + argsDescriptor;
  }
}
