/*
 * Copyright 2016 Google LLC
 *
 * 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.auto.value.processor;

import com.google.auto.common.MoreElements;
import com.google.auto.common.MoreTypes;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;

/**
 * Classifies methods inside builder types that return builders for properties. For example, if
 * {@code @AutoValue} class Foo has a method {@code ImmutableList<String> bar()} then Foo.Builder
 * can have a method {@code ImmutableList.Builder<String> barBuilder()}. This class checks that a
 * method like {@code barBuilder()} follows the rules, and if so constructs a {@link
 * PropertyBuilder} instance with information about {@code barBuilder}.
 *
 * @author Éamonn McManus
 */
class PropertyBuilderClassifier {
  private final ErrorReporter errorReporter;
  private final Types typeUtils;
  private final Elements elementUtils;
  private final BuilderMethodClassifier builderMethodClassifier;
  private final ImmutableBiMap<ExecutableElement, String> getterToPropertyName;
  private final ImmutableMap<ExecutableElement, TypeMirror> getterToPropertyType;
  private final EclipseHack eclipseHack;

  PropertyBuilderClassifier(
      ErrorReporter errorReporter,
      Types typeUtils,
      Elements elementUtils,
      BuilderMethodClassifier builderMethodClassifier,
      ImmutableBiMap<ExecutableElement, String> getterToPropertyName,
      ImmutableMap<ExecutableElement, TypeMirror> getterToPropertyType,
      EclipseHack eclipseHack) {
    this.errorReporter = errorReporter;
    this.typeUtils = typeUtils;
    this.elementUtils = elementUtils;
    this.builderMethodClassifier = builderMethodClassifier;
    this.getterToPropertyName = getterToPropertyName;
    this.getterToPropertyType = getterToPropertyType;
    this.eclipseHack = eclipseHack;
  }

  /**
   * Information about a property builder, referenced from the autovalue.vm template. A property
   * called bar (defined by a method bar() or getBar()) can have a property builder called
   * barBuilder(). For example, if {@code bar()} returns {@code ImmutableSet<String>} then {@code
   * barBuilder()} might return {@code ImmutableSet.Builder<String>}.
   */
  public static class PropertyBuilder {
    private final ExecutableElement propertyBuilderMethod;
    private final String name;
    private final String builderType;
    private final TypeMirror builderTypeMirror;
    private final String initializer;
    private final String beforeInitDefault;
    private final String initDefault;
    private final String builtToBuilder;
    private final String copyAll;

    PropertyBuilder(
        ExecutableElement propertyBuilderMethod,
        String builderType,
        TypeMirror builderTypeMirror,
        String initializer,
        String beforeInitDefault,
        String initDefault,
        String builtToBuilder,
        String copyAll) {
      this.propertyBuilderMethod = propertyBuilderMethod;
      this.name = propertyBuilderMethod.getSimpleName() + "$";
      this.builderType = builderType;
      this.builderTypeMirror = builderTypeMirror;
      this.initializer = initializer;
      this.beforeInitDefault = beforeInitDefault;
      this.initDefault = initDefault;
      this.builtToBuilder = builtToBuilder;
      this.copyAll = copyAll;
    }

    /** The property builder method, for example {@code barBuilder()}. */
    public ExecutableElement getPropertyBuilderMethod() {
      return propertyBuilderMethod;
    }

    public String getAccess() {
      return SimpleMethod.access(propertyBuilderMethod);
    }

    /** The name of the field to hold this builder. */
    public String getName() {
      return name;
    }

    /** The type of the builder, for example {@code ImmutableSet.Builder<String>}. */
    public String getBuilderType() {
      return builderType;
    }

    TypeMirror getBuilderTypeMirror() {
      return builderTypeMirror;
    }

    /** An initializer for the builder field, for example {@code ImmutableSet.builder()}. */
    public String getInitializer() {
      return initializer;
    }

    /**
     * An empty string, or a complete statement to be included before the expression returned by
     * {@link #getInitDefault()}.
     */
    public String getBeforeInitDefault() {
      return beforeInitDefault;
    }

    /**
     * An expression to return a default instance of the type that this builder builds. For example,
     * if this is an {@code ImmutableList<String>} then the method {@code ImmutableList.of()} will
     * correctly return an empty {@code ImmutableList<String>}, assuming the appropriate context for
     * type inference. The expression here can assume that the statement from {@link
     * #getBeforeInitDefault} has preceded it.
     */
    public String getInitDefault() {
      return initDefault;
    }

    /**
     * A method to convert the built type back into a builder. Unfortunately Guava collections don't
     * have this (you can't say {@code myImmutableMap.toBuilder()}), but for other types such as
     * {@code @AutoValue} types this is {@code toBuilder()}.
     */
    public String getBuiltToBuilder() {
      return builtToBuilder;
    }

    /**
     * The method to copy another collection into this builder. It is {@code addAll} for
     * one-dimensional collections like {@code ImmutableList} and {@code ImmutableSet}, and it is
     * {@code putAll} for two-dimensional collections like {@code ImmutableMap} and {@code
     * ImmutableTable}.
     */
    public String getCopyAll() {
      return copyAll;
    }
  }

  // Our @AutoValue class `Foo` has a property `Bar bar()` or `Bar getBar()` and we've encountered
  // a builder method like `BarBuilder barBuilder()`. Here `BarBuilder` can have any name (its name
  // doesn't have to be the name of `Bar` with `Builder` stuck on the end), but `barBuilder()` does
  // have to be the name of the property with `Builder` stuck on the end. The requirements for the
  // `BarBuilder` type are:
  // (1) It must have an instance method called `build()` that returns `Bar`. If the type of
  //     `bar()` is `Bar<String>` then the type of `build()` must be `Bar<String>`.
  // (2) `BarBuilder` must have a public no-arg constructor, or `Bar` must have a static method
  //     `naturalOrder(), `builder()`, or `newBuilder()` that returns `BarBuilder`. The
  //     `naturalOrder()` case is specifically for ImmutableSortedSet and ImmutableSortedMap.
  // (3) If `Foo` has a `toBuilder()` method, or if we have both `barBuilder()` and `setBar(Bar)`
  //     methods, then `Bar` must have an instance method `BarBuilder toBuilder()`, or `BarBuilder`
  //     must have an `addAll` or `putAll` method that accepts an argument of type `Bar`.
  //
  // This method outputs an error and returns Optional.empty() if the barBuilder() method has a
  // problem.
  Optional<PropertyBuilder> makePropertyBuilder(ExecutableElement method, String property) {
    TypeMirror barBuilderTypeMirror = builderMethodClassifier.builderMethodReturnType(method);
    if (barBuilderTypeMirror.getKind() != TypeKind.DECLARED) {
      errorReporter.reportError(
          method,
          "Method looks like a property builder, but its return type is not a class or interface");
      return Optional.empty();
    }
    DeclaredType barBuilderDeclaredType = MoreTypes.asDeclared(barBuilderTypeMirror);
    TypeElement barBuilderTypeElement = MoreTypes.asTypeElement(barBuilderTypeMirror);
    Map<String, ExecutableElement> barBuilderNoArgMethods = noArgMethodsOf(barBuilderTypeElement);

    ExecutableElement barGetter = getterToPropertyName.inverse().get(property);
    TypeMirror barTypeMirror = getterToPropertyType.get(barGetter);
    if (barTypeMirror.getKind() != TypeKind.DECLARED) {
      errorReporter.reportError(
          method,
          "Method looks like a property builder, but the type of property %s is not a class or"
              + " interface",
          property);
      return Optional.empty();
    }
    if (isNullable(barGetter)) {
      errorReporter.reportError(
          barGetter,
          "Property %s has a property builder so it cannot be @Nullable",
          property);
    }
    TypeElement barTypeElement = MoreTypes.asTypeElement(barTypeMirror);
    Map<String, ExecutableElement> barNoArgMethods = noArgMethodsOf(barTypeElement);

    // Condition (1), must have build() method returning Bar.
    ExecutableElement build = barBuilderNoArgMethods.get("build");
    if (build == null || build.getModifiers().contains(Modifier.STATIC)) {
      errorReporter.reportError(
          method,
          "Method looks like a property builder, but it returns %s which does not have a"
              + " non-static build() method",
          barBuilderTypeElement);
      return Optional.empty();
    }

    // We've determined that `BarBuilder` has a method `build()`. But it must return `Bar`.
    // And if the type of `bar()` is Bar<String> then `BarBuilder.build()` must return Bar<String>.
    TypeMirror buildType = eclipseHack.methodReturnType(build, barBuilderDeclaredType);
    if (!MoreTypes.equivalence().equivalent(barTypeMirror, buildType)) {
      errorReporter.reportError(
          method,
          "Property builder for %s has type %s whose build() method returns %s instead of %s",
          property,
          barBuilderTypeElement,
          buildType,
          barTypeMirror);
      return Optional.empty();
    }

    Optional<ExecutableElement> maybeBuilderMaker =
        builderMaker(barNoArgMethods, barBuilderTypeElement);
    if (!maybeBuilderMaker.isPresent()) {
      errorReporter.reportError(
          method,
          "Method looks like a property builder, but its type %s does not have a public"
              + " constructor and %s does not have a static builder() or newBuilder() method that"
              + " returns %s",
          barBuilderTypeElement,
          barTypeElement,
          barBuilderTypeElement);
      return Optional.empty();
    }
    ExecutableElement builderMaker = maybeBuilderMaker.get();

    String barBuilderType = TypeEncoder.encodeWithAnnotations(barBuilderTypeMirror);
    String rawBarType = TypeEncoder.encodeRaw(barTypeMirror);
    String initializer =
        (builderMaker.getKind() == ElementKind.CONSTRUCTOR)
            ? "new " + barBuilderType + "()"
            : rawBarType + "." + builderMaker.getSimpleName() + "()";
    String builtToBuilder = null;
    String copyAll = null;
    ExecutableElement toBuilder = barNoArgMethods.get("toBuilder");
    if (toBuilder != null
        && !toBuilder.getModifiers().contains(Modifier.STATIC)
        && typeUtils.isAssignable(
            typeUtils.erasure(toBuilder.getReturnType()),
            typeUtils.erasure(barBuilderTypeMirror))) {
      builtToBuilder = toBuilder.getSimpleName().toString();
    } else {
      Optional<ExecutableElement> maybeCopyAll =
          addAllPutAll(barBuilderTypeElement, barBuilderDeclaredType, barTypeMirror);
      if (maybeCopyAll.isPresent()) {
        copyAll = maybeCopyAll.get().getSimpleName().toString();
      }
    }
    ExecutableElement barOf = barNoArgMethods.get("of");
    boolean hasOf = (barOf != null && barOf.getModifiers().contains(Modifier.STATIC));
    // An expression (initDefault) to make a default one of these, plus optionally a statement
    // (beforeInitDefault) that prepares the expression. For a collection, beforeInitDefault is
    // empty and initDefault is (e.g.) `ImmutableList.of()`. For a nested value type,
    // beforeInitDefault is (e.g.)
    //   `NestedAutoValueType.Builder foo$builder = NestedAutoValueType.builder();`
    // and initDefault is `foo$builder.build();`. The reason for the separate statement is to
    // exploit type inference rather than having to write `NestedAutoValueType.<Bar>build();`.
    String beforeInitDefault;
    String initDefault;
    if (hasOf) {
      beforeInitDefault = "";
      initDefault = rawBarType + ".of()";
    } else {
      String localBuilder = property + "$builder";
      beforeInitDefault = barBuilderType + " " + localBuilder + " = " + initializer + ";";
      initDefault = localBuilder + ".build()";
    }

    PropertyBuilder propertyBuilder =
        new PropertyBuilder(
            method,
            barBuilderType,
            barBuilderTypeMirror,
            initializer,
            beforeInitDefault,
            initDefault,
            builtToBuilder,
            copyAll);
    return Optional.of(propertyBuilder);
  }

  private static final ImmutableSet<String> BUILDER_METHOD_NAMES =
      ImmutableSet.of("naturalOrder", "builder", "newBuilder");

  // (2) `BarBuilder must have a public no-arg constructor, or `Bar` must have a visible static
  //      method `naturalOrder(), `builder()`, or `newBuilder()` that returns `BarBuilder`.
  private Optional<ExecutableElement> builderMaker(
      Map<String, ExecutableElement> barNoArgMethods, TypeElement barBuilderTypeElement) {
    for (String builderMethodName : BUILDER_METHOD_NAMES) {
      ExecutableElement method = barNoArgMethods.get(builderMethodName);
      if (method != null
          && method.getModifiers().contains(Modifier.STATIC)
          && typeUtils.isSameType(
              typeUtils.erasure(method.getReturnType()),
              typeUtils.erasure(barBuilderTypeElement.asType()))) {
        // TODO(emcmanus): check visibility. We don't want to require public for @AutoValue
        // builders. By not checking visibility we risk accepting something as a builder maker
        // and then failing when the generated code tries to call Bar.builder(). But the risk
        // seems small.
        return Optional.of(method);
      }
    }
    return ElementFilter.constructorsIn(barBuilderTypeElement.getEnclosedElements())
        .stream()
        .filter(c -> c.getParameters().isEmpty())
        .filter(c -> c.getModifiers().contains(Modifier.PUBLIC))
        .findFirst();
  }

  private Map<String, ExecutableElement> noArgMethodsOf(TypeElement type) {
    // Can't easily use ImmutableMap here because getAllMembers could return more than one method
    // with the same name.
    Map<String, ExecutableElement> methods = new LinkedHashMap<>();
    for (ExecutableElement method : ElementFilter.methodsIn(elementUtils.getAllMembers(type))) {
      if (method.getParameters().isEmpty() && !isStaticInterfaceMethodNotIn(method, type)) {
        methods.put(method.getSimpleName().toString(), method);
      }
    }
    return methods;
  }

  // Work around an Eclipse compiler bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=547185
  // The result of Elements.getAllMembers includes static methods declared in superinterfaces.
  // That's wrong because those aren't inherited. So this method checks whether the given method is
  // a static interface method not in the given type.
  private static boolean isStaticInterfaceMethodNotIn(ExecutableElement method, TypeElement type) {
    return method.getModifiers().contains(Modifier.STATIC)
        && !method.getEnclosingElement().equals(type)
        && method.getEnclosingElement().getKind().equals(ElementKind.INTERFACE);
  }

  private static final ImmutableSet<String> ADD_ALL_PUT_ALL = ImmutableSet.of("addAll", "putAll");

  // We have `Bar bar()` and `Foo.Builder toBuilder()` in the @AutoValue type Foo, and we have
  // `BarBuilder barBuilder()` in Foo.Builder. That means that we need to be able to make a
  // `BarBuilder` from a `Bar` as part of the implementation of `Foo.toBuilder()`. We can do that
  // if `Bar` has a method `BarBuilder toBuilder()`, but what if it doesn't? For example, Guava's
  // `ImmutableList` doesn't have a method `ImmutableList.Builder toBuilder()`. So we also allow it
  // to work if `BarBuilder` has a method `addAll(T)` or `putAll(T)`, where `Bar` is assignable to
  // `T`. `ImmutableList.Builder<E>` does have a method `addAll(Iterable<? extends E>)` and
  // `ImmutableList<E>` is assignable to `Iterable<? extends E>`, so that works.
  private Optional<ExecutableElement> addAllPutAll(
      TypeElement barBuilderTypeElement,
      DeclaredType barBuilderDeclaredType,
      TypeMirror barTypeMirror) {
    return MoreElements.getLocalAndInheritedMethods(barBuilderTypeElement, typeUtils, elementUtils)
        .stream()
        .filter(
            method ->
                ADD_ALL_PUT_ALL.contains(method.getSimpleName().toString())
                    && method.getParameters().size() == 1)
        .filter(
            method -> {
              ExecutableType methodMirror =
                  MoreTypes.asExecutable(typeUtils.asMemberOf(barBuilderDeclaredType, method));
              return typeUtils.isAssignable(barTypeMirror, methodMirror.getParameterTypes().get(0));
            })
        .findFirst();
  }

  private static boolean isNullable(ExecutableElement getter) {
    List<List<? extends AnnotationMirror>> annotationLists =
        ImmutableList.of(
            getter.getAnnotationMirrors(), getter.getReturnType().getAnnotationMirrors());
    for (List<? extends AnnotationMirror> annotations : annotationLists) {
      for (AnnotationMirror annotation : annotations) {
        if (annotation.getAnnotationType().asElement().getSimpleName().contentEquals("Nullable")) {
          return true;
        }
      }
    }
    return false;
  }
}
