/*
 * 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() };
    }

    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;
  }
}
