/*
 * Copyright 2011 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.jjs.impl;

import com.google.gwt.dev.jjs.Correlation.Literal;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JArrayType;
import com.google.gwt.dev.jjs.ast.JClassLiteral;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JDeclarationStatement;
import com.google.gwt.dev.jjs.ast.JEnumType;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JField.Disposition;
import com.google.gwt.dev.jjs.ast.JFieldRef;
import com.google.gwt.dev.jjs.ast.JInterfaceType;
import com.google.gwt.dev.jjs.ast.JLiteral;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodBody;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JNullLiteral;
import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JPrimitiveType;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JRuntimeTypeReference;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.RuntimeConstants;
import com.google.gwt.dev.jjs.ast.js.JsniClassLiteral;
import com.google.gwt.dev.jjs.ast.js.JsniMethodBody;
import com.google.gwt.dev.jjs.ast.js.JsniMethodRef;
import com.google.gwt.dev.js.ast.JsContext;
import com.google.gwt.dev.js.ast.JsInvocation;
import com.google.gwt.dev.js.ast.JsModVisitor;
import com.google.gwt.dev.js.ast.JsNameRef;
import com.google.gwt.dev.js.ast.JsNumberLiteral;
import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
import com.google.gwt.thirdparty.guava.common.base.Joiner;
import com.google.gwt.thirdparty.guava.common.collect.ArrayListMultimap;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableMap;
import com.google.gwt.thirdparty.guava.common.collect.Iterables;
import com.google.gwt.thirdparty.guava.common.collect.Lists;
import com.google.gwt.thirdparty.guava.common.collect.Maps;
import com.google.gwt.thirdparty.guava.common.collect.Multimap;
import com.google.gwt.thirdparty.guava.common.collect.Sets;

import java.util.Map;
import java.util.Set;

/**
 * Create fields to represent the mechanical implementation of class literals.
 * Must be done after all class literals are created, but before optimizations
 * begin. {@link ControlFlowAnalyzer} depends on this.
 * <p>
 * Class literals are implemented as static field references. The static fields
 * are all put into the special com.google.gwt.lang.ClassLiteralHolder class.
 * Ordinarily, accessing one of these fields would trigger a clinit to run, but
 * we've special-cased class literal fields to evaluate as top-level code before
 * the application starts running to avoid the clinit.
 *
 * Class literal factory methods are responsible for installing references
 * to themselves on the Object.clazz field of their JS runtime prototype
 * since getClass() is no longer an overridden method.  Prototypes can be
 * looked up via 'typeId' from the global prototypesByTypeId object, and so each
 * class literal factory method is passed the typeId of its type.
 * <p>
 */
public class ImplementClassLiteralsAsFields {
  private static Map<Class<? extends JType>, ClassLiteralFactoryMethod>
      literalFactoryMethodByTypeClass  = new ImmutableMap.Builder()
          .put(JEnumType.class, ClassLiteralFactoryMethod.CREATE_FOR_ENUM)
          .put(JClassType.class, ClassLiteralFactoryMethod.CREATE_FOR_CLASS)
          .put(JInterfaceType.class, ClassLiteralFactoryMethod.CREATE_FOR_INTERFACE)
          .put(JPrimitiveType.class, ClassLiteralFactoryMethod.CREATE_FOR_PRIMITIVE)
          .build();

  /**
   * Class used to construct invocations to class literal factory methods.
   */
  public enum ClassLiteralFactoryMethod {
    CREATE_FOR_ENUM() {
      @Override
      JMethodCall createCall(SourceInfo info, JProgram program, JType type,
          JLiteral superclassLiteral) {
        JEnumType enumType = type.isEnumOrSubclass();
        assert enumType != null;

        // createForEnum(packageName, typeName, runtimeTypeReference, Enum.class,  type.values(),
        // type.valueOf(java/lang/String));
        JMethodCall call = createBaseCall(info, program, type, "Class.createForEnum");

        call.addArg(new JRuntimeTypeReference(info, program.getTypeJavaLangObject(),
            (JReferenceType) type));
        call.addArg(superclassLiteral);

        call.addArg(getStandardMethodAsArg(info, program, type, "values()"));
        call.addArg(getStandardMethodAsArg(info, program, type, "valueOf(Ljava/lang/String;)"));
        return call;
      }

      private JExpression getStandardMethodAsArg(SourceInfo info, JProgram program, JType type,
          String methodSignature) {
        JEnumType enumType = type.isEnumOrSubclass();

        if (enumType != type) {
          // The type is an anonymous subclass that represents one of the enum values
          return JNullLiteral.INSTANCE;
        }

        // This type is the base enum type not one of the anonymous classes that represent
        // enum values.
        for (JMethod method : enumType.getMethods()) {
          if (method.isStatic() && method.getSignature().startsWith(methodSignature)) {
            return new JsniMethodRef(info, method.getJsniSignature(true, false),
                method, program.getJavaScriptObject());
          }
        }

        // The method was pruned.
        return JNullLiteral.INSTANCE;
      }
    },
    CREATE_FOR_CLASS() {
      @Override
      JMethodCall createCall(SourceInfo info, JProgram program, JType type,
          JLiteral superclassLiteral) {

        // Class.createForClass(packageName, typeName, runtimeTypeReference, superclassliteral)
        JMethodCall call =
            createBaseCall(info, program, type, RuntimeConstants.CLASS_CREATE_FOR_CLASS);

        call.addArg(new JRuntimeTypeReference(info, program.getTypeJavaLangObject(),
            (JReferenceType) type));
        call.addArg(superclassLiteral);
        return call;
      }
    },
    CREATE_FOR_PRIMITIVE() {
      @Override
      JMethodCall createCall(SourceInfo info, JProgram program, JType type,
          JLiteral superclassLiteral) {

        // Class.createForPrimitive(typeName, typeSignature)
        JMethodCall call = new JMethodCall(info, null, program.getIndexedMethod(
                RuntimeConstants.CLASS_CREATE_FOR_PRIMITIVE));
        call.addArg(program.getStringLiteral(info, type.getShortName()));
        call.addArg(program.getStringLiteral(info, type.getJavahSignatureName()));
        return call;
      }
    },
    CREATE_FOR_INTERFACE() {
      @Override
      JMethodCall createCall(SourceInfo info, JProgram program, JType type,
          JLiteral superclassLiteral) {

        // Class.createForInterface(packageName, typeName)
        return createBaseCall(info, program, type, RuntimeConstants.CLASS_CREATE_FOR_INTERFACE);
      }
    };

    abstract JMethodCall createCall(SourceInfo info, JProgram program, JType type,
        JLiteral superclassLiteral);

    private static JMethodCall createBaseCall(SourceInfo info, JProgram program, JType type,
        String indexedMethodName) {

      String[] compoundName = maybeMangleJSOTypeName(type);
      JMethodCall call = new JMethodCall(info, null, program.getIndexedMethod(indexedMethodName),
          program.getStringLiteral(info, type.getPackageName()),
          getCompoundNameLiteral(program, info, compoundName));

      return call;
    }

    private static String[] maybeMangleJSOTypeName(JType type) {
      assert !(type instanceof JArrayType);
      String[] compoundName = type.getCompoundName();

      // Mangle the class name to match hosted mode.
      if (type.isJsoType()) {
        compoundName[compoundName.length - 1] = compoundName[compoundName.length - 1] + '$';
      }
      return compoundName;
    }

    private static JExpression getCompoundNameLiteral(final JProgram program, final SourceInfo info,
        String[] compoundName) {
      return program.getStringLiteral(info, Joiner.on('/').join(compoundName));
    }
  }

  private class NormalizeVisitor extends JModVisitor {
    @Override
    public void endVisit(JClassLiteral x, Context ctx) {
      JType type = x.getRefType();
      if (type instanceof JArrayType) {
        // Replace array class literals by an expression to obtain the class literal from the
        // leaf type of the array.
        JArrayType arrayType = (JArrayType) type;
        JClassLiteral leafTypeClassLiteral =
            new JClassLiteral(x.getSourceInfo(), arrayType.getLeafType());
        resolveClassLiteral(leafTypeClassLiteral);

        int dims = type.isJsNative() ? 1 : arrayType.getDims();
        JExpression arrayClassLiteralExpression = program.createArrayClassLiteralExpression(
            x.getSourceInfo(), leafTypeClassLiteral, dims);
        ctx.replaceMe(arrayClassLiteralExpression);
      } else {
        // Just resolve the class literal.
        resolveClassLiteral(x);
      }
    }

    @Override
    public void endVisit(JMethod x, Context ctx) {
      if (x.isJsMethodVarargs()) {
        // ImplementJsVarargs might insert an array creation for the varargs parameter which is not
        // seen by this pass.
        JParameter varargsParameter = Iterables.getLast(x.getParams());
        assert varargsParameter.isVarargs();
        resolveClassLiteralField(((JArrayType) varargsParameter.getType()).getLeafType());
      }
    }

    @Override
    public void endVisit(JsniClassLiteral x, Context ctx) {
      // JsniClassLiterals will be traversed explicitly in JsniMethodBody. For each JsniClassLiteral
      // in JsniMethodBody.classRefs there is at least a corresponding JsNameRef (with a jsni
      // identifier) that needs to be altered accordingly.
    }

    @Override
    public void endVisit(final JsniMethodBody jsniMethodBody, Context ctx) {
      if (jsniMethodBody.getClassRefs().size() == 0) {
        return;
      }

      final Multimap<String, JsniClassLiteral> jsniClassLiteralsByJsniReference =
          ArrayListMultimap.create();
      final JMethod getClassLiteralForArrayMethod =
          program.getIndexedMethod(RuntimeConstants.ARRAY_GET_CLASS_LITERAL_FOR_ARRAY);
      final String getClassLiteralForArrayMethodIdent =
          "@" + getClassLiteralForArrayMethod.getJsniSignature(true, false);

      boolean areThereArrayClassLiterals = false;
      for (JsniClassLiteral jsniClassLiteral : jsniMethodBody.getClassRefs()) {

        // Check for the presence of array class literals.
        if (jsniClassLiteral.getRefType() instanceof JArrayType) {
          areThereArrayClassLiterals = true;
        } else {
          // Resolve non array class literals.
          resolveClassLiteral(jsniClassLiteral);
        }

        // Map JSNI reference string to the actual JsniClassLiterals.
        jsniClassLiteralsByJsniReference.put(jsniClassLiteral.getIdent(), jsniClassLiteral);
      }

      if (!areThereArrayClassLiterals) {
        // No array class literal no need to explore the body.
        return;
      }

      final Set<JsniClassLiteral> newClassRefs = Sets.newLinkedHashSet();

      // Replace all arrays JSNI class literals with the its construction via the leaf type class
      // literal.
      JsModVisitor replaceJsniClassLiteralVisitor = new JsModVisitor() {

        @Override
        public void endVisit(JsNameRef x, JsContext ctx) {
          if (!x.isJsniReference()) {
            return;
          }

          if (jsniClassLiteralsByJsniReference.get(x.getIdent()).isEmpty()) {
            // The JsNameRef is not a class literal.
            return;
          }

          JsniClassLiteral jsniClassLiteral = jsniClassLiteralsByJsniReference.get(
              x.getIdent()).iterator().next();
          jsniClassLiteralsByJsniReference.remove(x.getIdent(), jsniClassLiteral);

          if (jsniClassLiteral.getRefType() instanceof JArrayType) {
            // Replace the array class literal by an expression that retrieves it from
            // that of the leaf type.
            JArrayType arrayType = (JArrayType) jsniClassLiteral.getRefType();
            JType leafType = arrayType.getLeafType();

            jsniClassLiteral = new JsniClassLiteral(jsniClassLiteral.getSourceInfo(), leafType);

            // Array.getClassLiteralForArray(leafType.class, dimensions)
            SourceInfo info = x.getSourceInfo();
            JsNameRef getArrayClassLiteralMethodNameRef =
                new JsNameRef(info, getClassLiteralForArrayMethodIdent);
            JsInvocation invocation = new JsInvocation(info, getArrayClassLiteralMethodNameRef,
                new JsNameRef(info, jsniClassLiteral.getIdent()),
                new JsNumberLiteral(info, arrayType.getDims()));
            // Finally resolve the class literal.
            resolveClassLiteral(jsniClassLiteral);
            ctx.replaceMe(invocation);
          }
          newClassRefs.add(jsniClassLiteral);
        }
      };
      replaceJsniClassLiteralVisitor.accept(jsniMethodBody.getFunc());
      if (!replaceJsniClassLiteralVisitor.didChange()) {
        // Nothing was changed, no need to replace JsniMethodBody.
        return;
      }

      JsniMethodBody newBody =
          new JsniMethodBody(jsniMethodBody.getSourceInfo(), jsniMethodBody.getFunc(),
          Lists.newArrayList(newClassRefs), jsniMethodBody.getJsniFieldRefs(),
          jsniMethodBody.getJsniMethodRefs(), jsniMethodBody.getUsedStrings());

      // Add getClassLiteralForArray as a JsniMethodRef.
      newBody.addJsniRef(
          new JsniMethodRef(jsniMethodBody.getSourceInfo(), getClassLiteralForArrayMethodIdent,
              getClassLiteralForArrayMethod, program.getJavaScriptObject()));

      ctx.replaceMe(newBody);
    }
  }

  public static void exec(JProgram program, boolean shouldOptimize) {
    Event normalizerEvent = SpeedTracerLogger.start(CompilerEventType.NORMALIZER);
    new ImplementClassLiteralsAsFields(program, shouldOptimize).execImpl();
    normalizerEvent.end();
  }

  private final Map<JType, JField> classLiteralFields = Maps.newIdentityHashMap();
  private final JMethodBody classLiteralHolderClinitBody;
  private final JProgram program;
  private final JClassType typeClassLiteralHolder;
  private final boolean shouldOptimize;

  private ImplementClassLiteralsAsFields(JProgram program, boolean shouldOptimize) {
    this.program = program;
    this.typeClassLiteralHolder = program.getTypeClassLiteralHolder();
    this.classLiteralHolderClinitBody =
        (JMethodBody) typeClassLiteralHolder.getClinitMethod().getBody();
    this.shouldOptimize = shouldOptimize;
    assert program.getDeclaredTypes().contains(typeClassLiteralHolder);
  }

  private JLiteral getSuperclassClassLiteral(SourceInfo info, JType type) {
    if (!(type instanceof JClassType) ||  ((JClassType) type).getSuperClass() == null) {
      return JNullLiteral.INSTANCE;
    }

    JClassType superClass = ((JClassType) type).getSuperClass();

    if (superClass.isJsNative()) {
      // Class object for subclasses of native JsType will return Object.class as their super class
      // class literal; this is done so that in invariant that "super" class literals are literals
      // of a actual superclass.
      superClass = program.getTypeJavaLangObject();
    }

    return createDependentClassLiteral(info, superClass);
  }

  private JClassLiteral createDependentClassLiteral(SourceInfo info, JType type) {
    JClassLiteral classLiteral = new JClassLiteral(info.makeChild(), type);
    classLiteral.setField(resolveClassLiteralField(classLiteral.getRefType()));
    return classLiteral;
  }

  private void execImpl() {
    if (!shouldOptimize) {
      // Create all class literals regardless of whether they are referenced or not.
      for (JPrimitiveType type : JPrimitiveType.types) {
        resolveClassLiteralField(type);
      }
      for (JType type : program.getDeclaredTypes()) {
        resolveClassLiteralField(type);
      }
    }
    NormalizeVisitor visitor = new NormalizeVisitor();
    visitor.accept(program);
    program.recordClassLiteralFields(classLiteralFields);
  }

  /**
   * Create an expression that will evaluate, at run time, to the class literal.
   * Causes recursive literal create (super type, array element type). Examples:
   *
   * Class:
   *
   * <pre>
   * Class.createForClass("java.lang.", "Object", /JRuntimeTypeReference/"java.lang.Object", null)
   * Class.createForClass("java.lang.", "Exception", /JRuntimeTypeReference/"java.lang.Exception",
   *   Throwable.class)
   * </pre>
   *
   * Interface:
   *
   * <pre>
   * Class.createForInterface(&quot;java.lang.&quot;, &quot;Comparable&quot;)
   * </pre>
   *
   * Arrays are lazily created.
   *
   * Primitive:
   *
   * <pre>
   * Class.createForPrimitive(&quot;&quot;, &quot;int&quot;, &quot;I&quot;)
   * </pre>
   *
   * Enum:
   *
   * <pre>
   * Class.createForEnum("com.example.", "MyEnum", /JRuntimeTypeReference/"com.example.MyEnum",
   *     Enum.class, public static MyEnum[] values(), public static MyEnum valueOf(String name))
   * </pre>
   *
   * Enum subclass:
   *
   * <pre>
   * Class.createForEnum("com.example.", "MyEnum$1", /JRuntimeTypeReference/"com.example.MyEnum$1",
   *   MyEnum.class, null, null))
   * </pre>
   */
  private JMethodCall createLiteralCall(SourceInfo info, JProgram program, JType type) {
    type = type.getUnderlyingType();

    Class<? extends JType>  typeClass = type.getClass();
    if (type.isEnumOrSubclass() != null) {
      typeClass = JEnumType.class;
    }

    return literalFactoryMethodByTypeClass.get(typeClass).createCall(info, program, type,
        getSuperclassClassLiteral(info, type));
  }

  private void resolveClassLiteral(JClassLiteral x) {
    JField field = resolveClassLiteralField(x.getRefType());
    x.setField(field);
  }

  /**
   * Resolve a class literal field. Takes the form:
   *
   * <pre>
   * class ClassLiteralHolder {
   *   Class Ljava_lang_Object_2_classLit =
   *       Class.createForClass("java.lang.", "Object", /JNameOf/"java.lang.Object", null)
   * }
   * </pre>
   */
  private JField resolveClassLiteralField(JType type) {
    type = type.isJsNative()
        ? program.getJavaScriptObject() : program.normalizeJsoType(type);
    JField field = classLiteralFields.get(type);
    if (field == null) {
      // Create the allocation expression FIRST since this may be recursive on
      // super type (this forces the super type classLit to be created first).
      SourceInfo info = type.getSourceInfo().makeChild();
      assert !(type instanceof JArrayType);

      JMethodCall classLiteralCreationExpression = createLiteralCall(info, program, type);

      // Create a field in the class literal holder to hold the object.
      field =
          new JField(info, getClassLiteralFieldName(type), typeClassLiteralHolder, program
              .getTypeJavaLangClass(), true, Disposition.FINAL);
      typeClassLiteralHolder.addField(field);
      info.addCorrelation(info.getCorrelator().by(Literal.CLASS));

      // Initialize the field.
      JFieldRef fieldRef = new JFieldRef(info, null, field, typeClassLiteralHolder);
      JDeclarationStatement decl =
          new JDeclarationStatement(info, fieldRef, classLiteralCreationExpression);
      classLiteralHolderClinitBody.getBlock().addStmt(decl);
      classLiteralFields.put(type, field);
    }
    return field;
  }

  private static String getClassLiteralFieldName(JType type) {
    return JjsUtils.classLiteralFieldNameFromJavahTypeSignatureName(type.getJavahSignatureName());
  }
}
