/*
 * Copyright (C) 2010 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.doclava;

import com.google.clearsilver.jsilver.data.Data;
import com.google.doclava.apicheck.AbstractMethodInfo;
import com.google.doclava.apicheck.ApiInfo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Queue;
import java.util.function.Predicate;

public class MethodInfo extends MemberInfo implements AbstractMethodInfo, Resolvable {
  public static final Comparator<MethodInfo> comparator = new Comparator<MethodInfo>() {
    @Override
    public int compare(MethodInfo a, MethodInfo b) {
      // TODO: expand to compare signature for better sorting
      return a.name().compareTo(b.name());
    }
  };

  private class InlineTags implements InheritedTags {
    public TagInfo[] tags() {
      return comment().tags();
    }

    public InheritedTags inherited() {
      MethodInfo m = findOverriddenMethod(name(), signature());
      if (m != null) {
        return m.inlineTags();
      } else {
        return null;
      }
    }
  }

  private static void addInterfaces(ArrayList<ClassInfo> ifaces, ArrayList<ClassInfo> queue) {
    for (ClassInfo i : ifaces) {
      queue.add(i);
    }
    for (ClassInfo i : ifaces) {
      addInterfaces(i.interfaces(), queue);
    }
  }

  // first looks for a superclass, and then does a breadth first search to
  // find the least far away match
  public MethodInfo findOverriddenMethod(String name, String signature) {
    if (mReturnType == null) {
      // ctor
      return null;
    }
    if (mOverriddenMethod != null) {
      return mOverriddenMethod;
    }

    ArrayList<ClassInfo> queue = new ArrayList<ClassInfo>();
    addInterfaces(containingClass().interfaces(), queue);
    for (ClassInfo iface : queue) {
      for (MethodInfo me : iface.methods()) {
        if (me.name().equals(name) && me.signature().equals(signature)
            && me.inlineTags().tags() != null && me.inlineTags().tags().length > 0) {
          return me;
        }
      }
    }
    return null;
  }

  private static void addRealInterfaces(ArrayList<ClassInfo> ifaces, ArrayList<ClassInfo> queue) {
    for (ClassInfo i : ifaces) {
      queue.add(i);
      if (i.realSuperclass() != null && i.realSuperclass().isAbstract()) {
        queue.add(i.superclass());
      }
    }
    for (ClassInfo i : ifaces) {
      addInterfaces(i.realInterfaces(), queue);
    }
  }

  public MethodInfo findRealOverriddenMethod(String name, String signature, HashSet notStrippable) {
    if (mReturnType == null) {
      // ctor
      return null;
    }
    if (mOverriddenMethod != null) {
      return mOverriddenMethod;
    }

    ArrayList<ClassInfo> queue = new ArrayList<ClassInfo>();
    if (containingClass().realSuperclass() != null
        && containingClass().realSuperclass().isAbstract()) {
      queue.add(containingClass().realSuperclass());
    }
    addInterfaces(containingClass().realInterfaces(), queue);
    for (ClassInfo iface : queue) {
      for (MethodInfo me : iface.methods()) {
        if (me.name().equals(name) && me.signature().equals(signature)
            && me.inlineTags().tags() != null && me.inlineTags().tags().length > 0
            && notStrippable.contains(me.containingClass())) {
          return me;
        }
      }
    }
    return null;
  }

  public MethodInfo findPredicateOverriddenMethod(Predicate<MemberInfo> predicate) {
    if (mReturnType == null) {
      // ctor
      return null;
    }
    if (mOverriddenMethod != null) {
      if (equals(mOverriddenMethod) && !mOverriddenMethod.isStatic()
          && predicate.test(mOverriddenMethod)) {
        return mOverriddenMethod;
      }
    }

    for (ClassInfo clazz : containingClass().gatherAncestorClasses()) {
      for (MethodInfo method : clazz.getExhaustiveMethods()) {
        if (equals(method) && !method.isStatic() && predicate.test(method)) {
          return method;
        }
      }
    }
    return null;
  }

  public ClassInfo findRealOverriddenClass(String name, String signature) {
    if (mReturnType == null) {
      // ctor
      return null;
    }
    if (mOverriddenMethod != null) {
      return mOverriddenMethod.mRealContainingClass;
    }

    ArrayList<ClassInfo> queue = new ArrayList<ClassInfo>();
    if (containingClass().realSuperclass() != null
        && containingClass().realSuperclass().isAbstract()) {
      queue.add(containingClass().realSuperclass());
    }
    addInterfaces(containingClass().realInterfaces(), queue);
    for (ClassInfo iface : queue) {
      for (MethodInfo me : iface.methods()) {
        if (me.name().equals(name) && me.signature().equals(signature)
            && me.inlineTags().tags() != null && me.inlineTags().tags().length > 0) {
          return iface;
        }
      }
    }
    return null;
  }

  private class FirstSentenceTags implements InheritedTags {
    public TagInfo[] tags() {
      return comment().briefTags();
    }

    public InheritedTags inherited() {
      MethodInfo m = findOverriddenMethod(name(), signature());
      if (m != null) {
        return m.firstSentenceTags();
      } else {
        return null;
      }
    }
  }

  private class ReturnTags implements InheritedTags {
    public TagInfo[] tags() {
      return comment().returnTags();
    }

    public InheritedTags inherited() {
      MethodInfo m = findOverriddenMethod(name(), signature());
      if (m != null) {
        return m.returnTags();
      } else {
        return null;
      }
    }
  }

  public boolean isDeprecated() {
    boolean deprecated = false;
    if (!mDeprecatedKnown) {
      boolean commentDeprecated = comment().isDeprecated();
      boolean annotationDeprecated = false;
      for (AnnotationInstanceInfo annotation : annotations()) {
        if (annotation.type().qualifiedName().equals("java.lang.Deprecated")) {
          annotationDeprecated = true;
          break;
        }
      }

      // Check to see that the JavaDoc contains @deprecated AND the method is marked as @Deprecated.
      // Otherwise, warn.
      // Note: We only do this for "included" classes (i.e. those we have source code for); we do
      // not have comments for classes from .class files but we do know whether a method is marked
      // as @Deprecated.
      if (mContainingClass.isIncluded() && !isHiddenOrRemoved()
          && commentDeprecated != annotationDeprecated) {
        Errors.error(Errors.DEPRECATION_MISMATCH, position(), "Method "
            + mContainingClass.qualifiedName() + "." + name()
            + ": @Deprecated annotation (" + (annotationDeprecated ? "" : "not ")
            + "present) and @deprecated doc tag (" + (commentDeprecated ? "" : "not ")
            + "present) do not match");
      }

      mIsDeprecated = commentDeprecated | annotationDeprecated;
      mDeprecatedKnown = true;
    }
    return mIsDeprecated;
  }

  public void setDeprecated(boolean deprecated) {
    mDeprecatedKnown = true;
    mIsDeprecated = deprecated;
  }

  public ArrayList<TypeInfo> getTypeParameters() {
    return mTypeParameters;
  }

  public boolean hasTypeParameters() {
      return mTypeParameters != null && !mTypeParameters.isEmpty();
  }

  /**
   * Clone this MethodInfo as if it belonged to the specified ClassInfo and apply the
   * typeArgumentMapping to the parameters and return types.
   */
  public MethodInfo cloneForClass(ClassInfo newContainingClass,
      Map<String, TypeInfo> typeArgumentMapping) {
    if (newContainingClass == containingClass()) {
      return this;
    }
    TypeInfo returnType = (mReturnType != null)
        ? mReturnType.getTypeWithArguments(typeArgumentMapping)
        : null;
    ArrayList<ParameterInfo> parameters = new ArrayList<ParameterInfo>();
    for (ParameterInfo pi : mParameters) {
      parameters.add(pi.cloneWithTypeArguments(typeArgumentMapping));
    }
    MethodInfo result =
        new MethodInfo(getRawCommentText(), mTypeParameters, name(), signature(),
            newContainingClass, realContainingClass(), isPublic(), isProtected(),
            isPackagePrivate(), isPrivate(), isFinal(), isStatic(), isSynthetic(), mIsAbstract,
            mIsSynchronized, mIsNative, mIsDefault, mIsAnnotationElement, kind(), mFlatSignature,
            mOverriddenMethod, returnType, mParameters, mThrownExceptions, position(),
            annotations());
    result.init(mDefaultAnnotationElementValue);
    return result;
  }

  public MethodInfo(String rawCommentText, ArrayList<TypeInfo> typeParameters, String name,
      String signature, ClassInfo containingClass, ClassInfo realContainingClass, boolean isPublic,
      boolean isProtected, boolean isPackagePrivate, boolean isPrivate, boolean isFinal,
      boolean isStatic, boolean isSynthetic, boolean isAbstract, boolean isSynchronized,
      boolean isNative, boolean isDefault, boolean isAnnotationElement, String kind,
      String flatSignature, MethodInfo overriddenMethod, TypeInfo returnType,
      ArrayList<ParameterInfo> parameters, ArrayList<ClassInfo> thrownExceptions,
      SourcePositionInfo position, ArrayList<AnnotationInstanceInfo> annotations) {
    // Explicitly coerce 'final' state of Java6-compiled enum values() method, to match
    // the Java5-emitted base API description.
    super(rawCommentText, name, signature, containingClass, realContainingClass, isPublic,
        isProtected, isPackagePrivate, isPrivate,
        ((name.equals("values") && containingClass.isEnum()) ? true : isFinal),
        isStatic, isSynthetic, kind, position, annotations);

    mReasonOpened = "0:0";
    mIsAnnotationElement = isAnnotationElement;
    mTypeParameters = typeParameters;
    mIsAbstract = isAbstract;
    mIsSynchronized = isSynchronized;
    mIsNative = isNative;
    mIsDefault = isDefault;
    mFlatSignature = flatSignature;
    mOverriddenMethod = overriddenMethod;
    mReturnType = returnType;
    mParameters = parameters;
    mThrownExceptions = thrownExceptions;
  }

  public void init(AnnotationValueInfo defaultAnnotationElementValue) {
    mDefaultAnnotationElementValue = defaultAnnotationElementValue;
  }

  public boolean isAbstract() {
    return mIsAbstract;
  }

  public boolean isSynchronized() {
    return mIsSynchronized;
  }

  public boolean isNative() {
    return mIsNative;
  }

  public boolean isDefault() {
    return mIsDefault;
  }

  public String flatSignature() {
    return mFlatSignature;
  }

  public InheritedTags inlineTags() {
    return new InlineTags();
  }

  public TagInfo[] blockTags() {
    return comment().blockTags();
  }

  public InheritedTags firstSentenceTags() {
    return new FirstSentenceTags();
  }

  public InheritedTags returnTags() {
    return new ReturnTags();
  }

  public TypeInfo returnType() {
    return mReturnType;
  }

  public String prettySignature() {
    return name() + prettyParameters();
  }

  public String prettyQualifiedSignature() {
    return qualifiedName() + prettyParameters();
  }

  /**
   * Returns a printable version of the parameters of this method's signature.
   */
  public String prettyParameters() {
    StringBuilder params = new StringBuilder("(");
    for (ParameterInfo pInfo : mParameters) {
      if (params.length() > 1) {
        params.append(",");
      }
      params.append(pInfo.type().simpleTypeName());
    }

    params.append(")");
    return params.toString();
  }

  /**
   * Returns a name consistent with the {@link com.google.doclava.MethodInfo#getHashableName()}.
   */
  public String getHashableName() {
    StringBuilder result = new StringBuilder();
    result.append(name());

    if (mParameters == null) {
        return result.toString();
    }

    int i = 0;
    for (ParameterInfo param : mParameters) {
      result.append(":");
      if (i == (mParameters.size()-1) && isVarArgs()) {
        // TODO: note that this does not attempt to handle hypothetical
        // vararg methods whose last parameter is a list of arrays, e.g.
        // "Object[]...".
        result.append(param.type().fullNameNoDimension(typeVariables())).append("...");
      } else {
        result.append(param.type().fullName(typeVariables()));
      }
      i++;
    }
    return result.toString();
  }

  private boolean inList(ClassInfo item, ThrowsTagInfo[] list) {
    int len = list.length;
    String qn = item.qualifiedName();
    for (int i = 0; i < len; i++) {
      ClassInfo ex = list[i].exception();
      if (ex != null && ex.qualifiedName().equals(qn)) {
        return true;
      }
    }
    return false;
  }

  public ThrowsTagInfo[] throwsTags() {
    if (mThrowsTags == null) {
      ThrowsTagInfo[] documented = comment().throwsTags();
      ArrayList<ThrowsTagInfo> rv = new ArrayList<ThrowsTagInfo>();

      int len = documented.length;
      for (int i = 0; i < len; i++) {
        rv.add(documented[i]);
      }

      for (ClassInfo cl : mThrownExceptions) {
        if (documented == null || !inList(cl, documented)) {
          rv.add(new ThrowsTagInfo("@throws", "@throws", cl.qualifiedName(), cl, "",
              containingClass(), position()));
        }
      }

      mThrowsTags = rv.toArray(ThrowsTagInfo.getArray(rv.size()));
    }
    return mThrowsTags;
  }

  private static int indexOfParam(String name, ParamTagInfo[] list) {
    final int N = list.length;
    for (int i = 0; i < N; i++) {
      if (name.equals(list[i].parameterName())) {
        return i;
      }
    }
    return -1;
  }

  /* Checks whether the name documented with the provided @param tag
   * actually matches one of the method parameters. */
  private boolean isParamTagInMethod(ParamTagInfo tag) {
    for (ParameterInfo paramInfo : mParameters) {
      if (paramInfo.name().equals(tag.parameterName())) {
        return true;
      }
    }
    return false;
  }

  public ParamTagInfo[] paramTags() {
    if (mParamTags == null) {
      final int N = mParameters.size();
      final String DEFAULT_COMMENT = "<!-- no parameter comment -->";

      if (N == 0) {
          // Early out for empty case.
          mParamTags = ParamTagInfo.EMPTY_ARRAY;
          return ParamTagInfo.EMPTY_ARRAY;
      }
      // Where we put each result
      mParamTags = ParamTagInfo.getArray(N);

      // collect all the @param tag info
      ParamTagInfo[] paramTags = comment().paramTags();

      // Complain about misnamed @param tags
      for (ParamTagInfo tag : paramTags) {
        if (!isParamTagInMethod(tag) && !tag.isTypeParameter()){
          Errors.error(Errors.UNKNOWN_PARAM_TAG_NAME, tag.position(),
              "@param tag with name that doesn't match the parameter list: '"
              + tag.parameterName() + "'");
        }
      }

      // Loop the parameters known from the method signature...
      // Start by getting the known parameter name and data type. Then, if
      // there's an @param tag that matches the current parameter name, get the
      // javadoc comments. But if there's no @param comments here, then
      // check if it's available from the parent class.
      int i = 0;
      for (ParameterInfo param : mParameters) {
        String name = param.name();
        String type = param.type().simpleTypeName();
        String comment = DEFAULT_COMMENT;
        SourcePositionInfo position = param.position();

        // Find the matching param from the @param tags in order to get
        // the parameter comments
        int index = indexOfParam(name, paramTags);
        if (index >= 0) {
          comment = paramTags[index].parameterComment();
          position = paramTags[index].position();
        }

        // get our parent's tags to fill in the blanks
        MethodInfo overridden = this.findOverriddenMethod(name(), signature());
        if (overridden != null) {
          ParamTagInfo[] maternal = overridden.paramTags();
          if (comment.equals(DEFAULT_COMMENT)) {
            comment = maternal[i].parameterComment();
            position = maternal[i].position();
          }
        }

        // Collect all docs requested by annotations
        TagInfo[] auxTags = Doclava.auxSource.paramAuxTags(this, param, comment);

        // Okay, now add the collected parameter information to the method data
        mParamTags[i] =
            new ParamTagInfo("@param", type, name + " " + comment, parent(),
                position, auxTags);

        // while we're here, if we find any parameters that are still
        // undocumented at this point, complain. This warning is off by
        // default, because it's really, really common;
        // but, it's good to be able to enforce it.
        if (comment.equals(DEFAULT_COMMENT)) {
          Errors.error(Errors.UNDOCUMENTED_PARAMETER, position,
              "Undocumented parameter '" + name + "' on method '"
              + name() + "'");
        } else {
          Doclava.linter.lintParameter(this, param, position, mParamTags[i]);
        }
        i++;
      }
    }
    return mParamTags;
  }

  public SeeTagInfo[] seeTags() {
    SeeTagInfo[] result = comment().seeTags();
    if (result == null) {
      if (mOverriddenMethod != null) {
        result = mOverriddenMethod.seeTags();
      }
    }
    return result;
  }

  public TagInfo[] deprecatedTags() {
    TagInfo[] result = comment().deprecatedTags();
    if (result.length == 0) {
      if (comment().undeprecateTags().length == 0) {
        if (mOverriddenMethod != null) {
          result = mOverriddenMethod.deprecatedTags();
        }
      }
    }
    return result;
  }

  public ArrayList<ParameterInfo> parameters() {
    return mParameters;
  }


  public boolean matchesParams(String[] params, String[] dimensions, boolean varargs) {
    if (mParamStrings == null) {
      if (mParameters.size() != params.length) {
        return false;
      }
      int i = 0;
      for (ParameterInfo mine : mParameters) {
        // If the method we're matching against is a varargs method (varargs == true), then
        // only its last parameter is varargs.
        if (!mine.matchesDimension(dimensions[i], (i == params.length - 1) ? varargs : false)) {
          return false;
        }
        TypeInfo myType = mine.type();
        String qualifiedName = myType.qualifiedTypeName();
        String realType = myType.isPrimitive() ? "" : myType.asClassInfo().qualifiedName();
        String s = params[i];

        // Check for a matching generic name or best known type
        if (!matchesType(qualifiedName, s) && !matchesType(realType, s)) {
          return false;
        }
        i++;
      }
    }
    return true;
  }

  /**
   * Checks to see if a parameter from a method signature is
   * compatible with a parameter given in a {@code @link} tag.
   */
  private boolean matchesType(String signatureParam, String callerParam) {
    int signatureLength = signatureParam.length();
    int callerLength = callerParam.length();
    return ((signatureParam.equals(callerParam) || ((callerLength + 1) < signatureLength
        && signatureParam.charAt(signatureLength - callerLength - 1) == '.'
        && signatureParam.endsWith(callerParam))));
  }

  public void makeHDF(Data data, String base) {
    makeHDF(data, base, Collections.<String, TypeInfo>emptyMap());
  }

  public void makeHDF(Data data, String base, Map<String, TypeInfo> typeMapping) {
    data.setValue(base + ".kind", kind());
    data.setValue(base + ".name", name());
    data.setValue(base + ".href", htmlPage());
    data.setValue(base + ".anchor", anchor());

    if (mReturnType != null) {
      returnType().getTypeWithArguments(typeMapping).makeHDF(
          data, base + ".returnType", false, typeVariables());
      data.setValue(base + ".abstract", mIsAbstract ? "abstract" : "");
    }

    data.setValue(base + ".default", mIsDefault ? "default" : "");
    data.setValue(base + ".synchronized", mIsSynchronized ? "synchronized" : "");
    data.setValue(base + ".final", isFinal() ? "final" : "");
    data.setValue(base + ".static", isStatic() ? "static" : "");

    TagInfo.makeHDF(data, base + ".shortDescr", firstSentenceTags());
    TagInfo.makeHDF(data, base + ".descr", inlineTags());
    TagInfo.makeHDF(data, base + ".descrAux", Doclava.auxSource.methodAuxTags(this));
    TagInfo.makeHDF(data, base + ".blockTags", blockTags());
    TagInfo.makeHDF(data, base + ".deprecated", deprecatedTags());
    TagInfo.makeHDF(data, base + ".seeAlso", seeTags());
    data.setValue(base + ".since", getSince());
    if (isDeprecated()) {
      data.setValue(base + ".deprecatedsince", getDeprecatedSince());
    }
    ParamTagInfo.makeHDF(data, base + ".paramTags", paramTags());
    AttrTagInfo.makeReferenceHDF(data, base + ".attrRefs", comment().attrTags());
    ThrowsTagInfo.makeHDF(data, base + ".throws", throwsTags());
    ParameterInfo.makeHDF(data, base + ".params", mParameters.toArray(
        new ParameterInfo[mParameters.size()]), isVarArgs(), typeVariables(), typeMapping);
    if (isProtected()) {
      data.setValue(base + ".scope", "protected");
    } else if (isPublic()) {
      data.setValue(base + ".scope", "public");
    }
    TagInfo.makeHDF(data, base + ".returns", returnTags());
    TagInfo.makeHDF(data, base + ".returnsAux", Doclava.auxSource.returnAuxTags(this));

    if (mTypeParameters != null) {
      TypeInfo.makeHDF(data, base + ".generic.typeArguments", mTypeParameters, false);
    }

    int numAnnotationDocumentation = 0;
    for (AnnotationInstanceInfo aii : annotations()) {
      String annotationDocumentation = Doclava.getDocumentationStringForAnnotation(
          aii.type().qualifiedName());
      if (annotationDocumentation != null) {
        data.setValue(base + ".annotationdocumentation." + numAnnotationDocumentation + ".text",
            annotationDocumentation);
        numAnnotationDocumentation++;
      }
    }

    AnnotationInstanceInfo.makeLinkListHDF(
      data,
      base + ".showAnnotations",
      showAnnotations().toArray(new AnnotationInstanceInfo[showAnnotations().size()]));

    setFederatedReferences(data, base);

    Doclava.linter.lintMethod(this);
  }

  public HashSet<String> typeVariables() {
    HashSet<String> result = TypeInfo.typeVariables(mTypeParameters);
    ClassInfo cl = containingClass();
    while (cl != null) {
        ArrayList<TypeInfo> types = cl.asTypeInfo().typeArguments();
      if (types != null) {
        TypeInfo.typeVariables(types, result);
      }
      cl = cl.containingClass();
    }
    return result;
  }

  @Override
  public boolean isExecutable() {
    return true;
  }

  public ArrayList<ClassInfo> thrownExceptions() {
    return mThrownExceptions;
  }

  public String typeArgumentsName(HashSet<String> typeVars) {
    if (!hasTypeParameters()) {
      return "";
    } else {
      return TypeInfo.typeArgumentsName(mTypeParameters, typeVars);
    }
  }

  public boolean isAnnotationElement() {
    return mIsAnnotationElement;
  }

  public AnnotationValueInfo defaultAnnotationElementValue() {
    return mDefaultAnnotationElementValue;
  }

  public void setVarargs(boolean set) {
    mIsVarargs = set;
  }

  public boolean isVarArgs() {
    return mIsVarargs;
  }

  public boolean isEffectivelyFinal() {
      if (mIsFinal) {
          return true;
      }
      ClassInfo containingClass = containingClass();
      if (containingClass != null && containingClass.isEffectivelyFinal()) {
          return true;
      }
      return false;
  }

  @Override
  public String toString() {
    return this.name();
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    } else if (o instanceof MethodInfo) {
      final MethodInfo m = (MethodInfo) o;
      return mName.equals(m.mName) && signature().equals(m.signature());
    } else {
      return false;
    }
  }

  @Override
  public int hashCode() {
    return Objects.hash(mName, signature());
  }

  public void setReason(String reason) {
    mReasonOpened = reason;
  }

  public String getReason() {
    return mReasonOpened;
  }

  public void addException(String exec) {
    ClassInfo exceptionClass = new ClassInfo(exec);

    mThrownExceptions.add(exceptionClass);
  }

  public void addParameter(ParameterInfo p) {
    // Name information
    if (mParameters == null) {
        mParameters = new ArrayList<ParameterInfo>();
    }

    mParameters.add(p);
  }

  private String mFlatSignature;
  private MethodInfo mOverriddenMethod;
  private TypeInfo mReturnType;
  private boolean mIsAnnotationElement;
  private boolean mIsAbstract;
  private boolean mIsSynchronized;
  private boolean mIsNative;
  private boolean mIsVarargs;
  private boolean mDeprecatedKnown;
  private boolean mIsDeprecated;
  private boolean mIsDefault;
  private ArrayList<ParameterInfo> mParameters;
  private ArrayList<ClassInfo> mThrownExceptions;
  private String[] mParamStrings;
  private ThrowsTagInfo[] mThrowsTags;
  private ParamTagInfo[] mParamTags;
  private ArrayList<TypeInfo> mTypeParameters;
  private AnnotationValueInfo mDefaultAnnotationElementValue;
  private String mReasonOpened;
  private ArrayList<Resolution> mResolutions;

  // TODO: merge with droiddoc version (above)
  public String qualifiedName() {
    String parentQName = (containingClass() != null)
        ? (containingClass().qualifiedName() + ".") : "";
    // TODO: This logic doesn't work well with constructors, as name() for constructors already
    // contains the containingClass's name, leading to things like A.B.B() being rendered as A.B.A.B()
    return parentQName + name();
  }

  @Override
  public String signature() {
    if (mSignature == null) {
      StringBuilder params = new StringBuilder("(");
      for (ParameterInfo pInfo : mParameters) {
        if (params.length() > 1) {
          params.append(", ");
        }
        params.append(pInfo.type().fullName());
      }

      params.append(")");
      mSignature = params.toString();
    }
    return mSignature;
  }

  public boolean matches(MethodInfo other) {
    return prettySignature().equals(other.prettySignature());
  }

  public boolean throwsException(ClassInfo exception) {
    for (ClassInfo e : mThrownExceptions) {
      if (e.qualifiedName().equals(exception.qualifiedName())) {
        return true;
      }
    }
    return false;
  }

  public boolean isConsistent(MethodInfo mInfo) {
    boolean consistent = true;
    if (!mReturnType.isTypeVariable() && !mInfo.mReturnType.isTypeVariable()) {
      if (!mReturnType.equals(mInfo.mReturnType) ||
          mReturnType.dimension() != mInfo.mReturnType.dimension()) {
        consistent = false;
      }
    } else if (!mReturnType.isTypeVariable() && mInfo.mReturnType.isTypeVariable()) {
      List<ClassInfo> constraints = mInfo.resolveConstraints(mInfo.mReturnType);
      for (ClassInfo constraint : constraints) {
        if (!constraint.isAssignableTo(mReturnType.qualifiedTypeName())) {
          consistent = false;
        }
      }
    } else if (mReturnType.isTypeVariable() && !mInfo.mReturnType.isTypeVariable()) {
      // It's never valid to go from being a parameterized type to not being one.
      // This would drop the implicit cast breaking backwards compatibility.
      consistent = false;
    } else {
      // If both return types are parameterized then the constraints must be
      // exactly the same.
      List<ClassInfo> currentConstraints = mInfo.resolveConstraints(mReturnType);
      List<ClassInfo> newConstraints = mInfo.resolveConstraints(mInfo.mReturnType);
      if (currentConstraints.size() != newConstraints.size() ||
          currentConstraints.retainAll(newConstraints)) {
        consistent = false;
      }
    }

    if (!consistent) {
      Errors.error(Errors.CHANGED_TYPE, mInfo.position(), "Method "
          + mInfo.prettyQualifiedSignature() + " has changed return type from " + mReturnType
          + " to " + mInfo.mReturnType);
    }

    if (mIsAbstract != mInfo.mIsAbstract) {
      consistent = false;
      Errors.error(Errors.CHANGED_ABSTRACT, mInfo.position(), "Method "
          + mInfo.prettyQualifiedSignature() + " has changed 'abstract' qualifier");
    }

    if (mIsNative != mInfo.mIsNative) {
      consistent = false;
      Errors.error(Errors.CHANGED_NATIVE, mInfo.position(), "Method "
          + mInfo.prettyQualifiedSignature() + " has changed 'native' qualifier");
    }

    if (!mIsStatic) {
      // Compiler-generated methods vary in their 'final' qualifier between versions of
      // the compiler, so this check needs to be quite narrow. A change in 'final'
      // status of a method is only relevant if (a) the method is not declared 'static'
      // and (b) the method is not already inferred to be 'final' by virtue of its class.
      if (!isEffectivelyFinal() && mInfo.isEffectivelyFinal()) {
        consistent = false;
        Errors.error(Errors.ADDED_FINAL, mInfo.position(), "Method "
            + mInfo.prettyQualifiedSignature() + " has added 'final' qualifier");
      } else if (isEffectivelyFinal() && !mInfo.isEffectivelyFinal()) {
        consistent = false;
        Errors.error(Errors.REMOVED_FINAL, mInfo.position(), "Method "
            + mInfo.prettyQualifiedSignature() + " has removed 'final' qualifier");
      }
    }

    if (mIsStatic != mInfo.mIsStatic) {
      consistent = false;
      Errors.error(Errors.CHANGED_STATIC, mInfo.position(), "Method "
          + mInfo.prettyQualifiedSignature() + " has changed 'static' qualifier");
    }

    if (!scope().equals(mInfo.scope())) {
      consistent = false;
      Errors.error(Errors.CHANGED_SCOPE, mInfo.position(), "Method "
          + mInfo.prettyQualifiedSignature() + " changed scope from " + scope()
          + " to " + mInfo.scope());
    }

    if (!isDeprecated() == mInfo.isDeprecated()) {
      Errors.error(Errors.CHANGED_DEPRECATED, mInfo.position(), "Method "
          + mInfo.prettyQualifiedSignature() + " has changed deprecation state " + isDeprecated()
          + " --> " + mInfo.isDeprecated());
      consistent = false;
    }

    // see JLS 3 13.4.20 "Adding or deleting a synchronized modifier of a method does not break "
    // "compatibility with existing binaries."
    /*
    if (mIsSynchronized != mInfo.mIsSynchronized) {
      Errors.error(Errors.CHANGED_SYNCHRONIZED, mInfo.position(), "Method " + mInfo.qualifiedName()
          + " has changed 'synchronized' qualifier from " + mIsSynchronized + " to "
          + mInfo.mIsSynchronized);
      consistent = false;
    }
    */

    for (ClassInfo exception : thrownExceptions()) {
      if (!mInfo.throwsException(exception)) {
        // exclude 'throws' changes to finalize() overrides with no arguments
        if (!name().equals("finalize") || (!mParameters.isEmpty())) {
          Errors.error(Errors.CHANGED_THROWS, mInfo.position(), "Method "
              + mInfo.prettyQualifiedSignature() + " no longer throws exception "
              + exception.qualifiedName());
          consistent = false;
        }
      }
    }

    for (ClassInfo exec : mInfo.thrownExceptions()) {
      // exclude 'throws' changes to finalize() overrides with no arguments
      if (!throwsException(exec)) {
        if (!name().equals("finalize") || (!mParameters.isEmpty())) {
          Errors.error(Errors.CHANGED_THROWS, mInfo.position(), "Method "
              + mInfo.prettyQualifiedSignature() + " added thrown exception "
              + exec.qualifiedName());
          consistent = false;
        }
      }
    }

    return consistent;
  }

  public TypeInfo getTypeParameter(String qualifiedTypeName) {
    if (hasTypeParameters()) {
      for (TypeInfo parameter : mTypeParameters) {
        if (parameter.qualifiedTypeName().equals(qualifiedTypeName)) {
          return parameter;
        }
      }
    }
    return containingClass().getTypeParameter(qualifiedTypeName);
  }

  // Given a type parameter it returns a list of all of the classes and interfaces it must extend
  // and implement.
  private List<ClassInfo> resolveConstraints(TypeInfo type) {
    ApiInfo api = containingClass().containingPackage().containingApi();
    List<ClassInfo> classes = new ArrayList<>();
    Queue<TypeInfo> types = new LinkedList<>();
    types.add(type);
    while (!types.isEmpty()) {
      type = types.poll();
      if (!type.isTypeVariable()) {
        ClassInfo cl = api.findClass(type.qualifiedTypeName());
        if (cl != null) {
          classes.add(cl);
        }
      } else {
        TypeInfo parameter = getTypeParameter(type.qualifiedTypeName());
        if (parameter.extendsBounds() != null) {
          for (TypeInfo bound : parameter.extendsBounds()) {
            types.add(bound);
          }
        }
      }
    }
    return classes;
  }

  public void printResolutions() {
      if (mResolutions == null || mResolutions.isEmpty()) {
          return;
      }

      System.out.println("Resolutions for Method " + mName + mFlatSignature + ":");

      for (Resolution r : mResolutions) {
          System.out.println(r);
      }
  }

  public void addResolution(Resolution resolution) {
      if (mResolutions == null) {
          mResolutions = new ArrayList<Resolution>();
      }

      mResolutions.add(resolution);
  }

  public boolean resolveResolutions() {
      ArrayList<Resolution> resolutions = mResolutions;
      mResolutions = new ArrayList<Resolution>();

      boolean allResolved = true;
      for (Resolution resolution : resolutions) {
          StringBuilder qualifiedClassName = new StringBuilder();
          InfoBuilder.resolveQualifiedName(resolution.getValue(), qualifiedClassName,
                  resolution.getInfoBuilder());

          // if we still couldn't resolve it, save it for the next pass
          if ("".equals(qualifiedClassName.toString())) {
              mResolutions.add(resolution);
              allResolved = false;
          } else if ("thrownException".equals(resolution.getVariable())) {
              mThrownExceptions.add(InfoBuilder.Caches.obtainClass(qualifiedClassName.toString()));
          }
      }

      return allResolved;
  }
}
