/*
 * Copyright (C) 2021 The Dagger Authors.
 *
 * 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 dagger.internal.codegen.base;

import static androidx.room.compiler.processing.XElementKt.isMethod;
import static androidx.room.compiler.processing.XElementKt.isTypeElement;
import static androidx.room.compiler.processing.XElementKt.isVariableElement;
import static androidx.room.compiler.processing.XTypeKt.isArray;
import static androidx.room.compiler.processing.compat.XConverters.toJavac;
import static androidx.room.compiler.processing.compat.XConverters.toXProcessing;
import static com.google.common.base.Preconditions.checkNotNull;
import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
import static dagger.internal.codegen.xprocessing.XAnnotationValues.getKindName;
import static dagger.internal.codegen.xprocessing.XElements.asEnumEntry;
import static dagger.internal.codegen.xprocessing.XElements.asExecutable;
import static dagger.internal.codegen.xprocessing.XElements.asMethod;
import static dagger.internal.codegen.xprocessing.XElements.asTypeElement;
import static dagger.internal.codegen.xprocessing.XElements.asTypeParameter;
import static dagger.internal.codegen.xprocessing.XElements.asVariable;
import static dagger.internal.codegen.xprocessing.XElements.getKindName;
import static dagger.internal.codegen.xprocessing.XElements.isEnumEntry;
import static dagger.internal.codegen.xprocessing.XElements.isExecutable;
import static dagger.internal.codegen.xprocessing.XElements.isTypeParameter;
import static dagger.internal.codegen.xprocessing.XExecutableTypes.asMethodType;
import static dagger.internal.codegen.xprocessing.XExecutableTypes.getKindName;
import static dagger.internal.codegen.xprocessing.XExecutableTypes.isMethodType;
import static dagger.internal.codegen.xprocessing.XTypes.asArray;
import static dagger.internal.codegen.xprocessing.XTypes.getKindName;
import static dagger.internal.codegen.xprocessing.XTypes.isDeclared;
import static dagger.internal.codegen.xprocessing.XTypes.isTypeOf;
import static dagger.internal.codegen.xprocessing.XTypes.isWildcard;

import androidx.room.compiler.processing.XAnnotation;
import androidx.room.compiler.processing.XAnnotationValue;
import androidx.room.compiler.processing.XElement;
import androidx.room.compiler.processing.XExecutableElement;
import androidx.room.compiler.processing.XExecutableType;
import androidx.room.compiler.processing.XProcessingEnv;
import androidx.room.compiler.processing.XProcessingEnv.Backend;
import androidx.room.compiler.processing.XType;
import androidx.room.compiler.processing.XTypeElement;
import androidx.room.compiler.processing.compat.XConverters;
import com.google.common.base.Ascii;
import com.google.common.collect.ImmutableList;
import com.google.devtools.ksp.symbol.ClassKind;
import com.squareup.javapoet.ClassName;
import dagger.Reusable;
import dagger.internal.codegen.compileroption.CompilerOptions;
import dagger.internal.codegen.xprocessing.XAnnotationValues;
import dagger.internal.codegen.xprocessing.XAnnotations;
import dagger.internal.codegen.xprocessing.XElements;
import dagger.internal.codegen.xprocessing.XExecutableTypes;
import dagger.internal.codegen.xprocessing.XTypes;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import javax.inject.Inject;

/**
 * A fork of {@link com.google.auto.common.SuperficialValidation}.
 *
 * <p>This fork makes a couple changes from the original:
 *
 * <ul>
 *   <li>Throws {@link ValidationException} rather than returning {@code false} for invalid types.
 *   <li>Fixes a bug that incorrectly validates error types in annotations (b/213880825)
 *   <li>Exposes extra methods needed to validate various parts of an element rather than just the
 *       entire element.
 * </ul>
 */
@Reusable
public final class DaggerSuperficialValidation {
  /**
   * Returns the type element with the given class name or throws {@link ValidationException} if it
   * is not accessible in the current compilation.
   */
  public static XTypeElement requireTypeElement(XProcessingEnv processingEnv, ClassName className) {
    return requireTypeElement(processingEnv, className.canonicalName());
  }

  /**
   * Returns the type element with the given class name or throws {@link ValidationException} if it
   * is not accessible in the current compilation.
   */
  public static XTypeElement requireTypeElement(XProcessingEnv processingEnv, String className) {
    XTypeElement type = processingEnv.findTypeElement(className);
    if (type == null) {
      throw new ValidationException.KnownErrorType(className);
    }
    return type;
  }

  private final boolean isStrictValidationEnabled;
  private final XProcessingEnv processingEnv;

  @Inject
  DaggerSuperficialValidation(XProcessingEnv processingEnv, CompilerOptions compilerOptions) {
    this.processingEnv = processingEnv;
    this.isStrictValidationEnabled = compilerOptions.strictSuperficialValidation();
  }

  /**
   * Validates the {@link XElement#getType()} type of the given element.
   *
   * <p>Validating the type also validates any types it references, such as any type arguments or
   * type bounds. For an {@link XExecutableType}, the parameter and return types must be fully
   * defined, as must types declared in a {@code throws} clause or in the bounds of any type
   * parameters.
   */
  public void validateTypeOf(XElement element) {
    try {
      // In XProcessing, there is no generic way to get an element "asType" so we break this down
      // differently for different element kinds.
      if (isTypeElement(element)) {
        XTypeElement typeElement = asTypeElement(element);
        // TODO(b/247828057): Due to a bug in XProcessing, enum entry types are sometimes
        // represented by XTypeElement rather than XEnumEntry in KSP which leads to failures later
        // on. Thus, skip validation in these cases until this bug is fixed.
        if (!(processingEnv.getBackend() == Backend.KSP
                && XConverters.toKS(typeElement).getClassKind() == ClassKind.ENUM_ENTRY)) {
          validateType(Ascii.toLowerCase(getKindName(element)), typeElement.getType());
        }
      } else if (isVariableElement(element)) {
        validateType(
            Ascii.toLowerCase(getKindName(element)) + " type", asVariable(element).getType());
      } else if (isExecutable(element)) {
        validateExecutableType(asExecutable(element).getExecutableType());
      } else if (isEnumEntry(element)) {
        validateType(
            Ascii.toLowerCase(getKindName(element)),
            asEnumEntry(element).getEnumTypeElement().getType());
      }
    } catch (RuntimeException exception) {
      throw ValidationException.from(exception).append(element);
    }
  }

  /**
   * Validates the {@link XElement#getSuperType()} type of the given element.
   *
   * <p>Validating the type also validates any types it references, such as any type arguments or
   * type bounds.
   */
  public void validateSuperTypeOf(XTypeElement element) {
    try {
      validateType("superclass", element.getSuperType());
    } catch (RuntimeException exception) {
      throw ValidationException.from(exception).append(element);
    }
  }

  /**
   * Validates the {@link XExecutableElement#getThrownTypes()} types of the given element.
   *
   * <p>Validating the type also validates any types it references, such as any type arguments or
   * type bounds.
   */
  public void validateThrownTypesOf(XExecutableElement element) {
    try {
      validateTypes("thrown type", element.getThrownTypes());
    } catch (RuntimeException exception) {
      throw ValidationException.from(exception).append(element);
    }
  }

  /**
   * Validates the annotation types of the given element.
   *
   * <p>Note: this method does not validate annotation values. This method is useful if you care
   * about the annotation's annotations (e.g. to check for {@code Scope} or {@code Qualifier}). In
   * such cases, we just need to validate the annotation's type.
   */
  public void validateAnnotationTypesOf(XElement element) {
    element
        .getAllAnnotations()
        .forEach(annotation -> validateAnnotationTypeOf(element, annotation));
  }

  /**
   * Validates the type of the given annotation.
   *
   * <p>The annotation is assumed to be annotating the given element, but this is not checked. The
   * element is only in the error message if a {@link ValidatationException} is thrown.
   *
   * <p>Note: this method does not validate annotation values. This method is useful if you care
   * about the annotation's annotations (e.g. to check for {@code Scope} or {@code Qualifier}). In
   * such cases, we just need to validate the annotation's type.
   */
  // TODO(bcorso): See CL/427767370 for suggestions to make this API clearer.
  public void validateAnnotationTypeOf(XElement element, XAnnotation annotation) {
    try {
      validateType("annotation type", annotation.getType());
    } catch (RuntimeException exception) {
      throw ValidationException.from(exception).append(annotation).append(element);
    }
  }

  /** Validate the annotations of the given element. */
  public void validateAnnotationsOf(XElement element) {
    try {
      validateAnnotations(element.getAllAnnotations());
    } catch (RuntimeException exception) {
      throw ValidationException.from(exception).append(element);
    }
  }

  public void validateAnnotationOf(XElement element, XAnnotation annotation) {
    try {
      validateAnnotation(annotation);
    } catch (RuntimeException exception) {
      throw ValidationException.from(exception).append(element);
    }
  }

  /**
   * Validate the type hierarchy for the given type (with the given type description) within the
   * given element.
   *
   * <p>Validation includes all superclasses, interfaces, and type parameters of those types.
   */
  public void validateTypeHierarchyOf(String typeDescription, XElement element, XType type) {
    try {
      validateTypeHierarchy(typeDescription, type);
    } catch (RuntimeException exception) {
      throw ValidationException.from(exception).append(element);
    }
  }

  private void validateTypeHierarchy(String desc, XType type) {
    validateType(desc, type);
    try {
      type.getSuperTypes().forEach(supertype -> validateTypeHierarchy("supertype", supertype));
    } catch (RuntimeException exception) {
      throw ValidationException.from(exception).append(desc, type);
    }
  }

  /**
   * Returns true if all of the given elements return true from {@link #validateElement(XElement)}.
   */
  private void validateElements(Collection<? extends XElement> elements) {
    elements.forEach(this::validateElement);
  }

  /**
   * Returns true if all types referenced by the given element are defined. The exact meaning of
   * this depends on the kind of element. For packages, it means that all annotations on the package
   * are fully defined. For other element kinds, it means that types referenced by the element,
   * anything it contains, and any of its annotations element are all defined.
   */
  public void validateElement(XElement element) {
    checkNotNull(element);

    // Validate the annotations first since these are common to all element kinds. We don't
    // need to wrap these in try-catch because the *Of() methods are already wrapped.
    validateAnnotationsOf(element);

    // Validate enclosed elements based on the given element's kind.
    try {
      if (isTypeElement(element)) {
        XTypeElement typeElement = asTypeElement(element);
        validateElements(typeElement.getTypeParameters());
        validateTypes("interface", typeElement.getSuperInterfaces());
        if (typeElement.getSuperType() != null) {
          validateType("superclass", typeElement.getSuperType());
        }
        validateElements(typeElement.getEnclosedElements());
      } else if (isExecutable(element)) {
        if (isMethod(element)) {
          validateType("return type", asMethod(element).getReturnType());
        }
        XExecutableElement executableElement = asExecutable(element);
        validateTypes("thrown type", executableElement.getThrownTypes());
        validateElements(executableElement.getTypeParameters());
        validateElements(executableElement.getParameters());
      } else if (isTypeParameter(element)) {
        validateTypes("bound type", asTypeParameter(element).getBounds());
      }
    } catch (RuntimeException exception) {
      throw ValidationException.from(exception).append(element);
    }

    // Validate the type last. This allows errors on more specific elements to be caught above.
    // E.g. errors on parameters will be attributed to the parameter elements rather than the method
    // type, which generally leads to nicer error messages. We don't need to wrap these in try-catch
    // because the *Of() methods are already wrapped.
    validateTypeOf(element);
  }

  private void validateTypes(String desc, Collection<? extends XType> types) {
    types.forEach(type -> validateType(desc, type));
  }

  /**
   * Returns true if the given type is fully defined. This means that the type itself is defined, as
   * are any types it references, such as any type arguments or type bounds.
   */
  private void validateType(String desc, XType type) {
    checkNotNull(type);
    // TODO(b/242569252): Due to a bug in kotlinc, a TypeName may incorrectly contain a "$" instead
    // of "." if the TypeName is requested before the type has been resolved. Furthermore,
    // XProcessing will cache the incorrect TypeName so that further calls will still contain the
    // "$" even after the type has been resolved. Thus, we try to resolve the type as early as
    // possible to prevent using/caching the incorrect TypeName.
    XTypes.resolveIfNeeded(type);
    try {
      if (isArray(type)) {
        validateType("array component type", asArray(type).getComponentType());
      } else if (isDeclared(type)) {
        if (isStrictValidationEnabled) {
          // There's a bug in TypeVisitor which will visit the visitDeclared() method rather than
          // visitError() even when it's an ERROR kind. Thus, we check the kind directly here and
          // fail validation if it's an ERROR kind (see b/213880825).
          if (isErrorKind(type)) {
            throw new ValidationException.KnownErrorType(type);
          }
        }
        type.getTypeArguments().forEach(typeArg -> validateType("type argument", typeArg));
      } else if (isWildcard(type)) {
        if (type.extendsBound() != null) {
          validateType("extends bound type", type.extendsBound());
        }
      } else if (isErrorKind(type)) {
        throw new ValidationException.KnownErrorType(type);
      }
    } catch (RuntimeException e) {
      throw ValidationException.from(e).append(desc, type);
    }
  }

  // TODO(bcorso): Consider moving this over to XProcessing. There's some complication due to
  // b/248552462 and the fact that XProcessing also uses the error.NonExistentClass type for invalid
  // types in KSP, which we may want to keep as error kinds in KSP.
  private boolean isErrorKind(XType type) {
    // https://youtrack.jetbrains.com/issue/KT-34193/Kapt-CorrectErrorTypes-doesnt-work-for-generics
    // XProcessing treats 'error.NonExistentClass' as an error type. However, due to the bug in KAPT
    // (linked above), 'error.NonExistentClass' can still be referenced in the stub classes even
    // when 'correctErrorTypes=true' is enabled. Thus, we can't treat 'error.NonExistentClass' as an
    // actual error type, as that would completely prevent processing of stubs that exhibit this
    // bug. This behavior also matches how things work in Javac, as 'error.NonExistentClass' is
    // treated as a TypeKind.DECLARED rather than a TypeKind.ERROR since the type is a real class
    // that exists on the classpath.
    return type.isError()
        && !(processingEnv.getBackend() == Backend.JAVAC
            && type.getTypeName().toString().contentEquals("error.NonExistentClass"));
  }

  /**
   * Returns true if the given type is fully defined. This means that the parameter and return types
   * must be fully defined, as must types declared in a {@code throws} clause or in the bounds of
   * any type parameters.
   */
  private void validateExecutableType(XExecutableType type) {
    try {
      validateTypes("parameter type", type.getParameterTypes());
      validateTypes("thrown type", type.getThrownTypes());
      validateTypes("type variable", getTypeVariables(type));
      if (isMethodType(type)) {
        validateType("return type", asMethodType(type).getReturnType());
      }
    } catch (RuntimeException e) {
      throw ValidationException.from(e).append(type);
    }
  }

  private ImmutableList<XType> getTypeVariables(XExecutableType executableType) {
    switch (processingEnv.getBackend()) {
      case JAVAC:
        return toJavac(executableType).getTypeVariables().stream()
            .map(typeVariable -> toXProcessing(typeVariable, processingEnv))
            .collect(toImmutableList());
      case KSP:
        // TODO(b/247851395): Add a way to get type variables as XTypes from XExecutableType --
        // currently, we can only get TypeVariableNames from XMethodType. For now, just skip
        // validating type variables of methods in KSP.
        return ImmutableList.of();
    }
    throw new AssertionError("Unexpected backend: " + processingEnv.getBackend());
  }

  private void validateAnnotations(Collection<XAnnotation> annotations) {
    annotations.forEach(this::validateAnnotation);
  }

  private void validateAnnotation(XAnnotation annotation) {
    try {
      validateType("annotation type", annotation.getType());
      validateAnnotationValues(getDefaultValues(annotation));
      validateAnnotationValues(annotation.getAnnotationValues());
    } catch (RuntimeException exception) {
      throw ValidationException.from(exception).append(annotation);
    }
  }

  private ImmutableList<XAnnotationValue> getDefaultValues(XAnnotation annotation) {
    switch (processingEnv.getBackend()) {
      case JAVAC:
        return annotation.getTypeElement().getDeclaredMethods().stream()
            .map(XConverters::toJavac)
            .filter(method -> method.getDefaultValue() != null)
            .map(method -> toXProcessing(method.getDefaultValue(), method, processingEnv))
            .collect(toImmutableList());
      case KSP:
        // TODO(b/231170716): Add a generic way to retrieve default values from XAnnotation
        // For now, just ignore them in KSP when doing validation.
        return ImmutableList.of();
    }
    throw new AssertionError("Unexpected backend: " + processingEnv.getBackend());
  }

  private void validateAnnotationValues(Collection<XAnnotationValue> values) {
    values.forEach(this::validateAnnotationValue);
  }

  private void validateAnnotationValue(XAnnotationValue value) {
    try {
      XType expectedType = value.getValueType();

      // TODO(b/249834057): In KSP error types in annotation values are just null, so check this
      // first and throw KnownErrorType of "<error>" to match Javac for now.
      if (processingEnv.getBackend() == Backend.KSP && value.getValue() == null) {
        throw new ValidationException.KnownErrorType("<error>");
      }

      if (value.hasListValue()) {
        validateAnnotationValues(value.asAnnotationValueList());
      } else if (value.hasAnnotationValue()) {
        validateIsEquivalentType(value.asAnnotation().getType(), expectedType);
        validateAnnotation(value.asAnnotation());
      } else if (value.hasEnumValue()) {
        validateIsEquivalentType(value.asEnum().getEnumTypeElement().getType(), expectedType);
        validateElement(value.asEnum());
      } else if (value.hasTypeValue()) {
        validateType("annotation value type", value.asType());
      } else {
        // Validates all other types, e.g. primitives and String values.
        validateIsTypeOf(expectedType, ClassName.get(value.getValue().getClass()));
      }
    } catch (RuntimeException e) {
      throw ValidationException.from(e).append(value);
    }
  }

  private void validateIsTypeOf(XType expectedType, ClassName className) {
    if (!isTypeOf(expectedType.boxed(), className)) {
      throw new ValidationException.UnknownErrorType();
    }
  }

  private void validateIsEquivalentType(XType type, XType expectedType) {
    if (!XTypes.equivalence().equivalent(type, expectedType)) {
      throw new ValidationException.KnownErrorType(type);
    }
  }

  /**
   * A runtime exception that can be used during superficial validation to collect information about
   * unexpected exceptions during validation.
   */
  public abstract static class ValidationException extends RuntimeException {
    /** A {@link ValidationException} that originated from an unexpected exception. */
    public static final class UnexpectedException extends ValidationException {
      private UnexpectedException(Throwable throwable) {
        super(throwable);
      }
    }

    /** A {@link ValidationException} that originated from a known error type. */
    public static final class KnownErrorType extends ValidationException {
      private final String errorTypeName;

      private KnownErrorType(XType errorType) {
        this.errorTypeName = XTypes.toStableString(errorType);
      }

      private KnownErrorType(String errorTypeName) {
        this.errorTypeName = errorTypeName;
      }

      public String getErrorTypeName() {
        return errorTypeName;
      }
    }

    /** A {@link ValidationException} that originated from an unknown error type. */
    public static final class UnknownErrorType extends ValidationException {}

    private static ValidationException from(Throwable throwable) {
      if (throwable instanceof ValidationException) {
        // We only ever create one instance of the ValidationException.
        return (ValidationException) throwable;
      } else if (throwable instanceof TypeNotPresentException) {
        // XProcessing can throw TypeNotPresentException, so grab the error type from there if so.
        return new KnownErrorType(((TypeNotPresentException) throwable).typeName());
      }
      return new UnexpectedException(throwable);
    }

    private Optional<XElement> lastReportedElement = Optional.empty();
    private final List<String> messages = new ArrayList<>();

    private ValidationException() {
      super("");
    }

    private ValidationException(Throwable throwable) {
      super("", throwable);
    }

    /**
     * Appends a message for the given element and returns this instance of {@link
     * ValidationException}
     */
    private ValidationException append(XElement element) {
      lastReportedElement = Optional.of(element);
      return append(getMessageForElement(element));
    }

    /**
     * Appends a message for the given type and returns this instance of {@link ValidationException}
     */
    private ValidationException append(String desc, XType type) {
      return append(
          String.format(
              "type (%s %s): %s",
              getKindName(type),
              desc,
              XTypes.toStableString(type)));
    }

    /**
     * Appends a message for the given executable type and returns this instance of {@link
     * ValidationException}
     */
    private ValidationException append(XExecutableType type) {
      return append(
          String.format(
              "type (EXECUTABLE %s): %s",
              Ascii.toLowerCase(getKindName(type)),
              XExecutableTypes.toStableString(type)));
    }
    /**
     * Appends a message for the given annotation and returns this instance of {@link
     * ValidationException}
     */
    private ValidationException append(XAnnotation annotation) {
      // Note: Calling #toString() directly on the annotation throws NPE (b/216180336).
      return append(String.format("annotation: %s", XAnnotations.toStableString(annotation)));
    }

    /** Appends the given message and returns this instance of {@link ValidationException} */
    private ValidationException append(String message) {
      messages.add(message);
      return this;
    }

    /**
     * Appends a message for the given annotation value and returns this instance of {@link
     * ValidationException}
     */
    private ValidationException append(XAnnotationValue value) {
      return append(
          String.format(
              "annotation value (%s): %s=%s",
              getKindName(value),
              value.getName(),  // SUPPRESS_GET_NAME_CHECK
              XAnnotationValues.toStableString(value)));
    }

    @Override
    public String getMessage() {
      return String.format("\n  Validation trace:\n    => %s", getTrace());
    }

    public String getTrace() {
      return String.join("\n    => ", getMessageInternal().reverse());
    }

    private ImmutableList<String> getMessageInternal() {
      if (!lastReportedElement.isPresent()) {
        return ImmutableList.copyOf(messages);
      }
      // Append any enclosing element information if needed.
      List<String> newMessages = new ArrayList<>(messages);
      XElement element = lastReportedElement.get();
      while (shouldAppendEnclosingElement(element)) {
        element = element.getEnclosingElement();
        newMessages.add(getMessageForElement(element));
      }
      return ImmutableList.copyOf(newMessages);
    }

    private static boolean shouldAppendEnclosingElement(XElement element) {
      return element.getEnclosingElement() != null
          // We don't report enclosing elements for types because the type name should contain any
          // enclosing type and package information we need.
          && !isTypeElement(element)
          && (isExecutable(element.getEnclosingElement())
              || isTypeElement(element.getEnclosingElement()));
    }

    private String getMessageForElement(XElement element) {
      return String.format(
          "element (%s): %s",
          Ascii.toUpperCase(getKindName(element)),
          XElements.toStableString(element));
    }
  }
}
