/*
 * 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.rewrite.HostedModeClassRewriter.InstanceMethodOracle;
import com.google.gwt.dev.shell.rewrite.HostedModeClassRewriter.SingleJsoImplData;

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

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * Writes the implementation classes for JSO and its subtypes.
 *
 * Changes made by the base class:
 * <ol>
 * <li>The new type has the same name as the old type with a '$' appended.</li>
 * <li>All instance methods in the original type become static methods taking an
 * explicit <code>this</code> parameter. Such methods have the same stack
 * behavior as the original.</li>
 * </ol>
 */
abstract class WriteJsoImpl extends ClassVisitor {

  /**
   * This type implements JavaScriptObject.
   *
   * <ol>
   * <li>JavaScriptObject itself gets a new synthetic field to store the
   * underlying hosted mode reference.</li>
   * <li>Instance methods are added so that JavaScriptObject implements all
   * SingleJsoImpl interfaces.</li>
   * </ol>
   *
   */
  private static class ForJsoDollar extends WriteJsoImpl {
    /**
     * An unmodifiable set of descriptors containing
     * <code>JavaScriptObject</code> and all subclasses.
     */
    private final Set<String> jsoDescriptors;
    private final SingleJsoImplData jsoData;

    public ForJsoDollar(ClassVisitor cv, Set<String> jsoDescriptors,
        InstanceMethodOracle mapper, SingleJsoImplData jsoData) {
      super(cv, mapper);
      this.jsoDescriptors = jsoDescriptors;
      this.jsoData = jsoData;
    }

    @Override
    public void visit(int version, int access, String name, String signature,
        String superName, String[] interfaces) {

      ArrayList<String> jsoDescList = new ArrayList<String>();
      jsoDescList.addAll(jsoDescriptors);
      interfaces = jsoDescList.toArray(new String[jsoDescList.size()]);

      super.visit(version, access, name, signature, superName, interfaces);

      /*
       * Generate the synthetic "hostedModeReferece" field to contain the
       * underlying real reference to the JavaScript object.
       */
      FieldVisitor fv = visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC,
          HostedModeClassRewriter.REFERENCE_FIELD, "Ljava/lang/Object;", null,
          null);
      if (fv != null) {
        fv.visitEnd();
      }

      // Implement the trampoline methods
      for (String mangledName : jsoData.getMangledNames()) {
        List<Method> declarations = jsoData.getDeclarations(mangledName);
        List<Method> implementations = jsoData.getImplementations(mangledName);
        assert declarations.size() == implementations.size() : "Declaration / implementation size mismatch";

        Iterator<Method> declIterator = declarations.iterator();
        Iterator<Method> implIterator = implementations.iterator();

        while (declIterator.hasNext()) {
          assert implIterator.hasNext();
          writeTrampoline(mangledName, declIterator.next(), implIterator.next());
        }
      }
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String desc,
        String signature, String[] exceptions) {
      if (isCtor(name)) {
        // make the JavaScriptObject$ constructor public
        access &= ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED);
        access |= Opcodes.ACC_PUBLIC;
      }
      return super.visitMethod(access, name, desc, signature, exceptions);
    }

    /**
     * JSO methods are implemented as flyweight style, with the instance being
     * passed as the first parameter. This loop create instance methods on JSO$
     * for all of the mangled SingleJsoImpl interface method names. These
     * instance methods simply turn around and call the static-dispatch methods.
     * In Java, it might look like:
     *
     * <pre>
     * interface Interface {
     *   String someMethod(int a, double b);
     * }
     *
     * class J extends JSO implements I {
     *   public String com_google_Interface_someMethod(int a, double b) {
     *     return com.google.MyJso$.someMethod$(this, a, b);
     *   }
     * }
     * </pre>
     *
     * @param mangledName {@code com_google_gwt_sample_hello_client_Interface_a}
     * @param interfaceMethod {@code java.lang.String a(int, double)}
     * @param implementingMethod {@code static final java.lang.String
     *          a$(com.google.gwt.sample.hello.client.Jso, ...);}
     */
    private void writeTrampoline(String mangledName, Method interfaceMethod,
        Method implementingMethod) {
      assert implementingMethod.getArgumentTypes().length > 0;

      /*
       * The local descriptor is the same as the descriptor from the abstract
       * method in the interface.
       */
      String localDescriptor = interfaceMethod.getDescriptor();
      Method localMethod = new Method(mangledName, localDescriptor);

      /*
       * We also use the first argument to know which type to statically
       * dispatch to.
       */
      Type implementingType = Type.getType("L"
          + implementingMethod.getArgumentTypes()[0].getInternalName() + "$;");

      // Maybe create the method. This is marked final as a sanity check
      MethodVisitor mv = visitMethodNoRewrite(Opcodes.ACC_PUBLIC
          | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC, localMethod.getName(),
          localMethod.getDescriptor(), null, null);

      if (mv != null) {
        mv.visitCode();

        /*
         * It just so happens that the stack and local variable sizes are the
         * same, but they're kept distinct to aid in clarity should the dispatch
         * logic change.
         */
        int var = 0;
        int size = 0;

        for (Type t : implementingMethod.getArgumentTypes()) {
          size += t.getSize();
          mv.visitVarInsn(t.getOpcode(Opcodes.ILOAD), var);
          var += t.getSize();
        }

        // Make sure there's enough room for the return value
        size = Math.max(size, implementingMethod.getReturnType().getSize());

        mv.visitMethodInsn(Opcodes.INVOKESTATIC,
            implementingType.getInternalName(), implementingMethod.getName(),
            implementingMethod.getDescriptor(), false);
        mv.visitInsn(localMethod.getReturnType().getOpcode(Opcodes.IRETURN));
        mv.visitMaxs(size, var);
        mv.visitEnd();
      }
    }
  }

  /**
   * This type is used to implement subtypes of JSO.
   *
   * <ol>
   * <li>The new type's superclass is mangled by adding $.</li>
   * <li>Constructors are deleted.</li>
   * </ol>
   */
  private static class ForJsoInterface extends WriteJsoImpl {
    public ForJsoInterface(ClassVisitor cv, InstanceMethodOracle mapper) {
      super(cv, mapper);
    }

    @Override
    public void visit(int version, int access, String name, String signature,
        String superName, String[] interfaces) {
      // Reference the old superclass's implementation class.
      superName += '$';
      interfaces = null;

      super.visit(version, access, name, signature, superName, interfaces);
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String desc,
        String signature, String[] exceptions) {
      boolean isCtor = isCtor(name);
      if (isCtor) {
        // Don't copy over constructors except for JavaScriptObject itself.
        return null;
      }
      return super.visitMethod(access, name, desc, signature, exceptions);
    }
  }

  /**
   * Creates a ClassVisitor to implement a JavaScriptObject subtype. This will
   * select between a simple implementation for user-defined JSO subtypes and
   * the complex implementation for implementing JavaScriptObject$.
   */
  public static ClassVisitor create(ClassVisitor cv, String classDescriptor,
      Set<String> jsoDescriptors, InstanceMethodOracle mapper,
      SingleJsoImplData singleJsoImplData) {

    if (classDescriptor.equals(HostedModeClassRewriter.JAVASCRIPTOBJECT_IMPL_DESC)) {
      return new ForJsoDollar(cv, jsoDescriptors, mapper, singleJsoImplData);
    } else {
      return new ForJsoInterface(cv, mapper);
    }
  }

  /**
   * Maps methods to the class in which they are declared.
   */
  private final InstanceMethodOracle mapper;

  /**
   * The original name of the class being visited.
   */
  private String originalName;

  /**
   * Construct a new rewriter instance.
   *
   * @param cv the visitor to chain to
   * @param jsoDescriptors an unmodifiable set of descriptors containing
   *          <code>JavaScriptObject</code> and all subclasses
   * @param mapper maps methods to the class in which they are declared
   */
  private WriteJsoImpl(ClassVisitor cv, InstanceMethodOracle mapper) {
    super(Opcodes.ASM7, cv);
    this.mapper = mapper;
  }

  /**
   * Records the original name and resets access opcodes.
   */
  @Override
  public void visit(int version, int access, String name, String signature,
      String superName, String[] interfaces) {
    originalName = name;
    super.visit(version, Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC
        | Opcodes.ACC_SYNTHETIC, name + '$', signature, superName, interfaces);
  }

  /**
   * Mangle all instance methods declared in JavaScriptObject types.
   */
  @Override
  public MethodVisitor visitMethod(int access, String name, String desc,
      String signature, String[] exceptions) {
    boolean isCtor = isCtor(name);
    if (!isCtor && !isStatic(access) && !isObjectMethod(name + desc)) {
      access |= Opcodes.ACC_STATIC;
      desc = HostedModeClassRewriter.addSyntheticThisParam(getOriginalName(),
          desc);
      name = name + "$";
    }
    return super.visitMethod(access, name, desc, signature, exceptions);
  }

  protected String getOriginalName() {
    return originalName;
  }

  protected boolean isCtor(String name) {
    return "<init>".equals(name);
  }

  protected boolean isObjectMethod(String signature) {
    return "java/lang/Object".equals(mapper.findOriginalDeclaringClass(
        originalName, signature));
  }

  protected boolean isStatic(int access) {
    return (access & Opcodes.ACC_STATIC) != 0;
  }

  /**
   * Allows access to an unmodified visitMethod call.
   */
  protected MethodVisitor visitMethodNoRewrite(int access, String name,
      String desc, String signature, String[] exceptions) {
    return super.visitMethod(access, name, desc, signature, exceptions);
  }
}
