/*
 * 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.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.javac.asmbridge.EmptyVisitor;
import com.google.gwt.dev.shell.JsValueGlue;
import com.google.gwt.dev.util.log.speedtracer.DevModeEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.Method;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;

/**
 * This class performs any and all byte code rewriting needed to make hosted
 * mode work. Currently, it performs the following rewrites:
 * <ol>
 * <li>Rewrites all native methods into non-native thunks to call JSNI via
 * {@link com.google.gwt.dev.shell.JavaScriptHost}.</li>
 * <li>Rewrites all JSO types into an interface type (which retains the original
 * name) and an implementation type (which has a $ appended).</li>
 * <li>All JSO interface types are empty and mirror the original type hierarchy.
 * </li>
 * <li>All JSO impl types contain the guts of the original type, except that all
 * instance methods are reimplemented as statics.</li>
 * <li>Calls sites to JSO types rewritten to dispatch to impl types. Any virtual
 * calls are also made static. Static field references to JSO types reference
 * static fields in the impl class.</li>
 * <li>JavaScriptObject$ implements all the interface types and is the only
 * instantiable type.</li>
 * </ol>
 *
 * @see RewriteJsniMethods
 * @see RewriteRefsToJsoClasses
 * @see WriteJsoInterface
 * @see WriteJsoImpl
 */
public class HostedModeClassRewriter {
  /*
   * Note: this rewriter operates on a class-by-class basis and has no global
   * view on the entire system. However, its operation requires certain global
   * state information. Therefore, all such global state must be passed into the
   * constructor.
   */

  /**
   * Maps instance methods to the class in which they are declared. This must be
   * provided by the caller since it requires global program state.
   */
  public interface InstanceMethodOracle {

    /**
     * For a given instance method and declared enclosing class (which must be a
     * JSO subtype), find the class in which that method was originally
     * declared. Methods declared on Object will return "java/lang/Object".
     * Static methods will always return <code>declaredClass</code>.
     *
     * @param declaredClass a descriptor of the static type of the qualifier
     * @param signature the binary signature of the method
     * @return the descriptor of the class in which that method was declared,
     *         which will either be <code>declaredClass</code> or some
     *         superclass
     * @throws IllegalArgumentException if the method could not be found
     */
    String findOriginalDeclaringClass(String declaredClass, String signature);
  }

  /**
   * Contains data about how SingleJsoImpl methods are to be dispatched.
   */
  public interface SingleJsoImplData {
    /**
     * Returns the method declarations that should be generated for a given
     * mangled method name. {@link #getDeclarations} and
     * {@link #getImplementations} maintain a pairwise mapping.
     */
    List<Method> getDeclarations(String mangledName);

    /**
     * Returns the implementations that the method declarations above should
     * delegate to.{@link #getDeclarations} and {@link #getImplementations}
     * maintain a pairwise mapping.
     */
    List<Method> getImplementations(String mangledName);

    /**
     * Returns all of the mangled method names for SingleJsoImpl methods.
     */
    SortedSet<String> getMangledNames();

    /**
     * Returns the internal names of all interface types implemented by JSOs.
     */
    Set<String> getSingleJsoIntfTypes();
  }

  static final String JAVASCRIPTOBJECT_DESC = JsValueGlue.JSO_CLASS.replace(
      '.', '/');

  static final String JAVASCRIPTOBJECT_IMPL_DESC = JsValueGlue.JSO_IMPL_CLASS.replace(
      '.', '/');

  static final String REFERENCE_FIELD = JsValueGlue.HOSTED_MODE_REFERENCE;

  static String addSyntheticThisParam(String owner, String methodDescriptor) {
    return "(L" + owner + ";" + methodDescriptor.substring(1);
  }

  private static String toDescriptor(String jsoSubtype) {
    return jsoSubtype.replace('.', '/');
  }

  /**
   * An unmodifiable set of descriptors containing the implementation form of
   * <code>JavaScriptObject</code> and all subclasses.
   */
  private final Set<String> jsoImplDescs;

  /**
   * An unmodifiable set of descriptors containing the interface form of
   * <code>JavaScriptObject</code> and all subclasses.
   */
  private final Set<String> jsoIntfDescs;

  private final SingleJsoImplData jsoData;

  /**
   * Records the superclass of every JSO for generating empty JSO interfaces.
   */
  private final Map<String, List<String>> jsoSuperDescs;

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

  /**
   * Creates a new {@link HostedModeClassRewriter} for a specified set of
   * subclasses of JavaScriptObject.
   *
   * @param jsoSubtypes a set of binary type names representing JavaScriptObject
   *          and all of its subtypes of
   * @param mapper maps methods to the class in which they are declared
   */
  public HostedModeClassRewriter(Set<String> jsoSubtypes,
      Map<String, List<String>> jsoSuperTypes, SingleJsoImplData jsoData,
      InstanceMethodOracle mapper) {
    Set<String> buildJsoIntfDescs = new HashSet<String>();
    Set<String> buildJsoImplDescs = new HashSet<String>();
    Map<String, List<String>> buildJsoSuperDescs = new HashMap<String, List<String>>();
    for (String jsoSubtype : jsoSubtypes) {
      String desc = toDescriptor(jsoSubtype);
      buildJsoIntfDescs.add(desc);
      buildJsoImplDescs.add(desc + "$");

      List<String> superTypes = jsoSuperTypes.get(jsoSubtype);
      assert (superTypes != null);
      assert (superTypes.size() > 0);
      for (ListIterator<String> i = superTypes.listIterator(); i.hasNext();) {
        i.set(toDescriptor(i.next()));
      }
      buildJsoSuperDescs.put(desc, Collections.unmodifiableList(superTypes));
    }

    this.jsoIntfDescs = Collections.unmodifiableSet(buildJsoIntfDescs);
    this.jsoImplDescs = Collections.unmodifiableSet(buildJsoImplDescs);
    this.jsoSuperDescs = Collections.unmodifiableMap(buildJsoSuperDescs);
    this.jsoData = jsoData;
    this.mapper = mapper;
  }

  /**
   * Returns <code>true</code> if the class is the implementation class for a
   * JSO subtype.
   */
  public boolean isJsoImpl(String className) {
    return jsoImplDescs.contains(toDescriptor(className));
  }

  /**
   * Returns <code>true</code> if the class is the interface class for a JSO
   * subtype.
   */
  public boolean isJsoIntf(String className) {
    return jsoIntfDescs.contains(toDescriptor(className));
  }

  /**
   * Performs rewriting transformations on a class.
   *
   * @param typeOracle a typeOracle modeling the user classes
   * @param className the name of the class
   * @param classBytes the bytes of the class
   * @param anonymousClassMap a map between the anonymous class names of java
   *          compiler used to compile code and jdt. Emma-specific.
   */
  public byte[] rewrite(TypeOracle typeOracle, String className,
      byte[] classBytes, Map<String, String> anonymousClassMap) {
    Event classBytesRewriteEvent =
        SpeedTracerLogger.start(DevModeEventType.CLASS_BYTES_REWRITE, "Class Name", className);
    String desc = toDescriptor(className);
    assert (!jsoIntfDescs.contains(desc));

    // The ASM model is to chain a bunch of visitors together.
    ClassWriter writer = new ClassWriter(0);
    ClassVisitor v = writer;

    // v = new CheckClassAdapter(v);
    // v = new TraceClassVisitor(v, new PrintWriter(System.out));
    v = new UseMirroredClasses(v, className);

    v = new RewriteSingleJsoImplDispatches(v, typeOracle, jsoData);

    v = new RewriteRefsToJsoClasses(v, jsoIntfDescs, mapper);

    if (jsoImplDescs.contains(desc)) {
      v = WriteJsoImpl.create(v, desc, jsoIntfDescs, mapper, jsoData);
    }

    v = new RewriteJsniMethods(v, anonymousClassMap);

    if (Double.parseDouble(System.getProperty("java.class.version")) < Opcodes.V1_8) {
      // TODO(cromwellian) implement Retrolambda?
      v = new ForceClassVersion15(v);
    }

    new ClassReader(classBytes).accept(v, 0);
    classBytesRewriteEvent.end();
    return writer.toByteArray();
  }

  public byte[] writeJsoIntf(final String className, byte classBytes[]) {
    String desc = toDescriptor(className);
    assert (jsoIntfDescs.contains(desc));
    assert (jsoSuperDescs.containsKey(desc));
    List<String> superDescs = jsoSuperDescs.get(desc);
    assert (superDescs != null);
    assert (superDescs.size() > 0);

    // The ASM model is to chain a bunch of visitors together.
    ClassWriter writer = new ClassWriter(0);
    final ClassVisitor v = writer;

    // v = new CheckClassAdapter(v);
    // v = new TraceClassVisitor(v, new PrintWriter(System.out));

    String[] interfaces;
    // TODO(bov): something better than linear?
    if (superDescs.contains("java/lang/Object")) {
      interfaces = null;
    } else {
      interfaces = superDescs.toArray(new String[superDescs.size()]);
    }
    v.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC | Opcodes.ACC_INTERFACE, desc,
        null, "java/lang/Object", interfaces);
    if (classBytes != null) {
      // Java7 enforces innerclass/outerclass consistency. In order to fix this, copy from original
      ClassVisitor cv = new EmptyVisitor() {
        @Override
        public void visitInnerClass(String name, String outerName, String innerName,
            int access) {
          // copy inner class table from original JSO to synthetic interface
          v.visitInnerClass(name, outerName, innerName, access);
        }

        @Override
        public void visitOuterClass(String owner, String name, String desc) {
          // copy outer class table from original JSO to synthetic interface
          v.visitOuterClass(owner, name, desc);
        }
      };
      new ClassReader(classBytes).accept(cv, 0);
    }
    v.visitEnd();
    return writer.toByteArray();
  }
}
