/*
 * 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.jjs.ast;

import com.google.gwt.dev.javac.JsInteropUtil;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.impl.GwtAstBuilder;
import com.google.gwt.dev.jjs.impl.JjsUtils;
import com.google.gwt.dev.util.StringInterner;
import com.google.gwt.dev.util.collect.Lists;
import com.google.gwt.thirdparty.guava.common.base.Preconditions;
import com.google.gwt.thirdparty.guava.common.base.Predicates;
import com.google.gwt.thirdparty.guava.common.base.Strings;
import com.google.gwt.thirdparty.guava.common.collect.Iterables;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Set;

/**
 * Base class for any declared type.
 *
 * Declared types have fields and methods. Two of the methods are treated specially: the class
 * initializer method (named <code>$clinit</code>) and the instance initializer method
 * (named <code>$init</code>).
 *
 * The class initializer method is responsible for initializing all class variables as well as
 * those of the superclasses (by calling the superclass class initializer method).
 *
 * The instance initializer is responsible for initializing all instance variables as well as those
 * of the superclasses (by calling the superclass instance initializer method).
 *
 * Optimizations may eliminate class initializers (<code>$clinit</code>) if no static variables need
 * initialization, and use the private variable <code>clinitTarget</code>to keep track which
 * initializer in the superclass chain needs to be called.
 */
public abstract class JDeclaredType extends JReferenceType
    implements CanHaveSuppressedWarnings, HasJsName, CanBeJsNative {

  private boolean isJsFunction;
  private boolean isJsType;
  private boolean isClassWideExport;
  private boolean isJsNative;
  private String jsNamespace = null;
  private String jsName = null;
  private Set<String> suppressedWarnings;

  /**
   * The types of nested classes, https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
   */
  public enum NestedClassDisposition {
    /**
     * Static Nested Class.
     */
    STATIC,
    /**
     * Inner Nested Class.
     */
    INNER,
    /**
     * Local Class.
     */
    LOCAL(true),
    /**
     * Anonymous Inner Class.
     */
    ANONYMOUS(true),
    /**
     * Synthetic Inner Class from Lambda or method reference.
     */
    LAMBDA(true),
    /**
     * Regular top-level class.
     */
    TOP_LEVEL;

    private final boolean localType;

    NestedClassDisposition(boolean local) {
      this.localType = local;
    }

    NestedClassDisposition() {
      this.localType = false;
    }

    public boolean isLocalType() {
      return localType;
    }
  }

  private NestedClassDisposition nestedClassDisposition = NestedClassDisposition.TOP_LEVEL;

  /**
   * This type's fields. Special serialization treatment.
   */
  protected transient List<JField> fields = Lists.create();

  /**
   * This type's methods. Special serialization treatment.
   */
  protected transient List<JMethod> methods = Lists.create();

  /**
   * Tracks the target static initialization for this class. Default to self (if it has a non
   * empty initializer) or point to a superclass or be null.
   */
  private JDeclaredType clinitTarget = this;

  /**
   * The type which originally enclosed this type. Null if this class was a
   * top-level type. Note that all classes are converted to top-level types in
   * {@link com.google.gwt.dev.jjs.impl.GenerateJavaAST}; this information is
   * for tracking purposes.
   */
  private JDeclaredType enclosingType;

  /**
   * True if this class is provided externally to the program by the program's
   * host execution environment. For example, while compiling for the JVM, JRE
   * types are external types. External types definitions are provided by class
   * files which are considered opaque by the GWT compiler.
   */
  private boolean isExternal;

  /**
   * This type's implemented interfaces.
   */
  private List<JInterfaceType> superInterfaces = Lists.create();

  public JDeclaredType(SourceInfo info, String name) {
    super(info, name);
  }

  /**
   * Adds a field to this type.
   */
  public void addField(JField field) {
    assert field.getEnclosingType() == this;
    fields = Lists.add(fields, field);
  }

  /**
   * Adds an implemented interface to this type.
   */
  public void addImplements(JInterfaceType superInterface) {
    superInterfaces = Lists.add(superInterfaces, superInterface);
  }

  /**
   * Adds a method to this type.
   */
  public final void addMethod(int index, JMethod method) {
    assert method.getEnclosingType() == this;
    assert !method.getName().equals(GwtAstBuilder.CLINIT_METHOD_NAME)
        || getMethods().size() == 0
        : "Attempted adding $clinit method with index != 0";
    assert !method.getName().equals(GwtAstBuilder.INIT_NAME_METHOD_NAME)
        || method.getParams().size() != 0
        || getMethods().size() == 1
        : "Attempted adding $init method with index != 1";
    methods = Lists.add(methods, index, method);
  }

  public void addMethod(JMethod newMethod) {
    addMethod(methods.size(), newMethod);
  }

  /**
   * Returns <code>true</code> if a static field access of
   * <code>targetType</code> from within this type should generate a clinit
   * call. This will be true in cases where <code>targetType</code> has a live
   * clinit method which we cannot statically know has already run. We can
   * statically know the clinit method has already run when:
   * <ol>
   * <li><code>this == targetType</code></li>
   * <li><code>this</code> is a subclass of <code>targetType</code>, because my
   * clinit would have already run this <code>targetType</code>'s clinit; see
   * JLS 12.4</li>
   * </ol>
   */
  public boolean checkClinitTo(JDeclaredType targetType) {
    if (this == targetType) {
      // Call to self (very common case).
      return false;
    }
    if (targetType == null || !targetType.hasClinit()) {
      // Target has no clinit (common case).
      return false;
    }
    /*
     * The clinit for the source of the reference must already have run, so if
     * it's the same as this one, there it must have already run. One example is
     * a reference from a subclass to something in a superclass.
     */
    return this.getClinitTarget() != targetType.getClinitTarget();
  }

  /**
   * Returns the method with the given signature, if there is one.<br />
   *
   * Optionally can search up the super type chain.
   */
  public JMethod findMethod(String methodSignature, boolean recurse) {
    for (JMethod method : getMethods()) {
      if (method.getSignature().equals(methodSignature)) {
        return method;
      }
    }
    if (recurse && getSuperClass() != null) {
      return getSuperClass().findMethod(methodSignature, true);
    }
    return null;
  }

  /**
   * Determines whether a subclass of this type is in the collection <code>types</code>.
   *
   * @param types a collections of types.
   * @return the first subtype found in the collection  if the collection <code>types</code>
   *             contains a subtype of this type; null otherwise.
   */
  public JDeclaredType findSubtype(Iterable<JDeclaredType> types) {
    for (JDeclaredType type : types) {
      JDeclaredType tp = type;
      while (tp != null) {
        if (this == tp) {
          return type;
        }
        tp = tp.getSuperClass();
      }
    }
    return null;
  }

  /**
   * Returns the class initializer method.
   * Can only be called after making sure the class has a class initializer method.
   *
   * @return The class initializer method.
   */
  public final JMethod getClinitMethod() {
    assert getMethods().size() != 0;
    JMethod clinit = this.getMethods().get(GwtAstBuilder.CLINIT_METHOD_INDEX);

    assert clinit != null;
    assert clinit.getName().equals(GwtAstBuilder.CLINIT_METHOD_NAME);
    return clinit;
  }

  /**
   * Returns the class that must be initialized to use this class. May be a
   * superclass, or <code>null</code> if this class has no static initializer.
   */
  public final JDeclaredType getClinitTarget() {
    if (isJsFunction()) {
      return null;
    }
    return clinitTarget;
  }

  @Override
  public String[] getCompoundName() {
    // TODO(rluble): refactor the way names are constructed so that the ground data passed from
    // JDT is stored.
    if (enclosingType == null) {
      return new String[] { getShortName() };
    }

    assert getShortName().startsWith(enclosingType.getShortName())
        : "Innerclass name  " + getShortName() + " does not start with enclosing class name "
        + enclosingType.getShortName();

    String className = StringInterner.get().intern(
        getShortName().substring(enclosingType.getShortName().length() + 1));

    String[] enclosingCompoundName = enclosingType.getCompoundName();
    String[] compoundName = new String[enclosingCompoundName.length + 1];
    System.arraycopy(enclosingCompoundName, 0, compoundName, 0, enclosingCompoundName.length);
    compoundName[compoundName.length - 1] = className;
    return compoundName;
  }

  /**
   * Returns the simple source name for the class.
   * <p>e.g. if the class is a.b.Foo.Bar it returns Bar as opposed to the short name Foo$Bar.
   */
  public String getSimpleName() {
    String[] compoundName = getCompoundName();
    return compoundName[compoundName.length - 1];
  }

  /**
   * Returns the constructors for this type.
   */
  public Iterable<JConstructor> getConstructors() {
    return (Iterable) Iterables.filter(methods, Predicates.instanceOf(JConstructor.class));
  }

  /**
   * Returns the type which encloses this type.
   *
   * @return The enclosing type. May be {@code null}.
   */
  public JDeclaredType getEnclosingType() {
    return enclosingType;
  }

  /**
   * Returns this type's fields;does not include fields defined in a super type
   * unless they are overridden by this type.
   */
  public List<JField> getFields() {
    return fields;
  }

  /**
   * Returns this type's implemented interfaces. Returns an empty list if this
   * type implements no interfaces.
   */
  public List<JInterfaceType> getImplements() {
    return superInterfaces;
  }

  /**
   * Returns the instance initializer ($init) method.
   *
   * @return The instance initializer method.
   */
  public abstract JMethod getInitMethod();

  @Override
  public String getJavahSignatureName() {
    return JjsUtils.javahSignatureFromName(name);
  }

  @Override
  public String getJsniSignatureName() {
    return "L" + name.replace('.', '/') + ';';
  }

  /**
   * Returns this type's declared methods; does not include methods defined in a
   * super type unless they are overridden by this type.
   */
  public final List<JMethod> getMethods() {
    return methods;
  }

  public Iterable<JMember> getMembers() {
    return Iterables.<JMember>concat(fields, methods);
  }

  @Override
  public boolean isArrayType() {
    return false;
  }

  @Override
  public boolean isJsType() {
    return isJsType;
  }

  @Override
  public boolean isJsFunction() {
    return isJsFunction;
  }

  public boolean isClassWideExport() {
    return isClassWideExport;
  }

  public boolean hasJsInteropEntryPoints() {
    for (JMethod method : getMethods()) {
      if (method.isJsInteropEntryPoint()) {
        return true;
      }
    }

    for (JField field : getFields()) {
      if (field.isJsInteropEntryPoint()) {
        return true;
      }
    }

    return false;
  }

  @Override
  public boolean canBeReferencedExternally() {
    if (isJsType()) {
      return true;
    }
    for (JMember member : getMembers()) {
      if (member.canBeReferencedExternally()) {
        return true;
      }
    }
    return false;
  }

  @Override
  public boolean isJsNative() {
    return isJsNative;
  }

  @Override
  public boolean canBeImplementedExternally() {
    return isJsNative() || isJsFunction();
  }

  /**
   * Returns this type's super class, or <code>null</code> if this type is
   * {@link Object} or an interface.
   */
  public abstract JClassType getSuperClass();

  /**
   * Returns <code>true</code> when this class's clinit must be run dynamically.
   */
  public boolean hasClinit() {
    return getClinitTarget() != null;
  }

  @Override
  public boolean isExternal() {
    return isExternal;
  }

  /**
   * Returns whether this type can be instantiated.
   */
  public boolean isInstantiable() {
    if (isAbstract()) {
      return false;
    }
    if (!(this instanceof JClassType) && !(this instanceof JEnumType)) {
      return false;
    }
    if (getDefaultConstructor() == null) {
      return false;
    }
    return true;
  }

  /**
   * Removes the field at the specified index.
   */
  public void removeField(int i) {
    assert !isExternal() : "External types can not be modified.";
    fields = Lists.remove(fields, i);
  }

  /**
   * Removes the method at the specified index.
   */
  public void removeMethod(int i) {
    assert !isExternal() : "External types can not be modified.";
    methods = Lists.remove(methods, i);
  }

  /**
   * Resolves external references during AST stitching.
   */
  public void resolve(List<JInterfaceType> resolvedInterfaces, JDeclaredType pkgInfo) {
    assert JType.replaces(resolvedInterfaces, superInterfaces);
    superInterfaces = Lists.normalize(resolvedInterfaces);
    if (jsNamespace == null) {
      jsNamespace = computeJsNamespace(pkgInfo);
    }
  }

  private String computeJsNamespace(JDeclaredType pkgInfo) {
    if (enclosingType != null) {
      return enclosingType.getQualifiedJsName();
    }
    return pkgInfo != null && pkgInfo.jsNamespace != null ? pkgInfo.jsNamespace : getPackageName();
  }

  /**
   * Sets the type which encloses this types.
   *
   * @param enclosingType May be {@code null}.
   */
  public void setEnclosingType(JDeclaredType enclosingType) {
    this.enclosingType = enclosingType;
  }

  public void setExternal(boolean isExternal) {
    this.isExternal = isExternal;
  }

  public void setJsTypeInfo(boolean isJsType, boolean isJsNative, boolean isJsFunction,
      String jsNamespace, String jsName, boolean isClassWideExport) {
    this.isJsType = isJsType;
    this.isJsNative = isJsNative;
    this.isJsFunction = isJsFunction;
    this.jsNamespace = jsNamespace;
    this.jsName = jsName;
    this.isClassWideExport = isClassWideExport;
  }

  /**
   * Sorts this type's fields according to the specified sort.
   */
  public void sortFields(Comparator<? super JField> sort) {
    fields = Lists.sort(fields, sort);
  }

  /**
   * Sorts this type's methods according to the specified sort.
   */
  public void sortMethods(Comparator<? super JMethod> sort) {
    // Sort the methods manually to avoid sorting clinit out of place!
    JMethod a[] = methods.toArray(new JMethod[methods.size()]);
    Arrays.sort(a, 1, a.length, sort);
    methods = Lists.create(a);
  }

  /**
   * Subclasses must replace themselves with a shallow reference when
   * {@link #isExternal()} is <code>true</code>.
   */
  protected abstract Object writeReplace();

  /**
   * See {@link #writeMembers(ObjectOutputStream)}.
   *
   * @see #writeMembers(ObjectOutputStream)
   */
  @SuppressWarnings("unchecked") void readMembers(ObjectInputStream stream)
      throws IOException, ClassNotFoundException {
    fields = (List<JField>) stream.readObject();
    methods = (List<JMethod>) stream.readObject();
  }

  /**
   * See {@link #writeMethodBodies(ObjectOutputStream)}.
   *
   * @see #writeMethodBodies(ObjectOutputStream)
   */
  void readMethodBodies(ObjectInputStream stream) throws IOException, ClassNotFoundException {
    for (JMethod method : methods) {
      method.readBody(stream);
    }
  }

  /**
   * Called to set this class's trivial initializer to point to a superclass.
   */
  void setClinitTarget(JDeclaredType newClinitTarget) {
    if (clinitTarget == newClinitTarget) {
      return;
    }
    if (newClinitTarget != null && getClass().desiredAssertionStatus()) {
      // Make sure this is a pure upgrade to a superclass or null.
      for (JClassType current = (JClassType) clinitTarget; current != newClinitTarget; current =
          current.getSuperClass()) {
        Preconditions.checkNotNull(current.getSuperClass(),
            "Null super class for: %s (currentTarget: %s; newTarget: %s) in %s", current,
            clinitTarget, newClinitTarget, this);
      }
    }
    clinitTarget = newClinitTarget;
  }

  /**
   * After all types are written to the stream without transient members, this
   * method actually writes fields and methods to the stream, which establishes
   * type identity for them.
   *
   * @see JProgram#writeObject(ObjectOutputStream)
   */
  void writeMembers(ObjectOutputStream stream) throws IOException {
    stream.writeObject(fields);
    stream.writeObject(methods);
  }

  /**
   * After all types, fields, and methods are written to the stream, this method
   * writes method bodies to the stream.
   *
   * @see JProgram#writeObject(ObjectOutputStream)
   */
  void writeMethodBodies(ObjectOutputStream stream) throws IOException {
    for (JMethod method : methods) {
      method.writeBody(stream);
    }
  }

  private JMethod getDefaultConstructor() {
    for (JMethod constructor : getConstructors()) {
      if (constructor.getOriginalParamTypes().size() == 0) {
        return constructor;
      }
    }
    return null;
  }

  @Override
  public String getJsName() {
    return Strings.isNullOrEmpty(jsName) ? getSimpleName() : jsName;
  }

  @Override
  public String getJsNamespace() {
    return jsNamespace;
  }

  @Override
  public String getQualifiedJsName() {
    return JsInteropUtil.isGlobal(jsNamespace) ? getJsName() : jsNamespace + "." + getJsName();
  }

  public NestedClassDisposition getClassDisposition() {
    return nestedClassDisposition;
  }

  public void setClassDisposition(NestedClassDisposition nestedClassDisposition) {
    this.nestedClassDisposition = nestedClassDisposition;
  }

  @Override
  public Set<String> getSuppressedWarnings() {
    return suppressedWarnings;
  }

  @Override
  public void setSuppressedWarnings(Set<String> suppressedWarnings) {
    this.suppressedWarnings = suppressedWarnings;
  }
}
