// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.shaking;

import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexAnnotationElement;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedAnnotation;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.GraphLense;
import com.android.tools.r8.graph.InnerClassAttribute;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;

public class AnnotationRemover {

  private final AppView<AppInfoWithLiveness> appView;
  private final ProguardKeepAttributes keep;
  private final Set<DexType> classesToRetainInnerClassAttributeFor;

  public AnnotationRemover(
      AppView<AppInfoWithLiveness> appView, Set<DexType> classesToRetainInnerClassAttributeFor) {
    this.appView = appView;
    this.keep = appView.options().getProguardConfiguration().getKeepAttributes();
    this.classesToRetainInnerClassAttributeFor = classesToRetainInnerClassAttributeFor;
  }

  /**
   * Used to filter annotations on classes, methods and fields.
   */
  private boolean filterAnnotations(DexAnnotation annotation) {
    return shouldKeepAnnotation(
        annotation, isAnnotationTypeLive(annotation), appView.dexItemFactory(), appView.options());
  }

  static boolean shouldKeepAnnotation(
      DexAnnotation annotation,
      boolean isAnnotationTypeLive,
      DexItemFactory dexItemFactory,
      InternalOptions options) {
    ProguardKeepAttributes config =
        options.getProguardConfiguration() != null
            ? options.getProguardConfiguration().getKeepAttributes()
            : ProguardKeepAttributes.fromPatterns(ImmutableList.of());

    switch (annotation.visibility) {
      case DexAnnotation.VISIBILITY_SYSTEM:
        // InnerClass and EnclosingMember are represented in class attributes, not annotations.
        assert !DexAnnotation.isInnerClassAnnotation(annotation, dexItemFactory);
        assert !DexAnnotation.isMemberClassesAnnotation(annotation, dexItemFactory);
        assert !DexAnnotation.isEnclosingMethodAnnotation(annotation, dexItemFactory);
        assert !DexAnnotation.isEnclosingClassAnnotation(annotation, dexItemFactory);
        if (config.exceptions && DexAnnotation.isThrowingAnnotation(annotation, dexItemFactory)) {
          return true;
        }
        if (config.signature && DexAnnotation.isSignatureAnnotation(annotation, dexItemFactory)) {
          return true;
        }
        if (config.sourceDebugExtension
            && DexAnnotation.isSourceDebugExtension(annotation, dexItemFactory)) {
          return true;
        }
        if (config.methodParameters
            && DexAnnotation.isParameterNameAnnotation(annotation, dexItemFactory)) {
          return true;
        }
        if (DexAnnotation.isAnnotationDefaultAnnotation(annotation, dexItemFactory)) {
          // These have to be kept if the corresponding annotation class is kept to retain default
          // values.
          return true;
        }
        return false;

      case DexAnnotation.VISIBILITY_RUNTIME:
        if (!config.runtimeVisibleAnnotations) {
          return false;
        }
        return isAnnotationTypeLive;

      case DexAnnotation.VISIBILITY_BUILD:
        if (DexAnnotation.isSynthesizedClassMapAnnotation(annotation, dexItemFactory)) {
          // TODO(sgjesse) When should these be removed?
          return true;
        }
        if (!config.runtimeInvisibleAnnotations) {
          return false;
        }
        return isAnnotationTypeLive;

      default:
        throw new Unreachable("Unexpected annotation visibility.");
    }
  }

  private boolean isAnnotationTypeLive(DexAnnotation annotation) {
    DexType annotationType = annotation.annotation.type.toBaseType(appView.dexItemFactory());
    DexClass definition = appView.definitionFor(annotationType);
    // TODO(b/73102187): How to handle annotations without definition.
    if (appView.options().isShrinking() && definition == null) {
      return false;
    }
    return appView.appInfo().isNonProgramTypeOrLiveProgramType(annotationType);
  }

  /**
   * Used to filter annotations on parameters.
   */
  private boolean filterParameterAnnotations(DexAnnotation annotation) {
    switch (annotation.visibility) {
      case DexAnnotation.VISIBILITY_SYSTEM:
        return false;
      case DexAnnotation.VISIBILITY_RUNTIME:
        if (!keep.runtimeVisibleParameterAnnotations) {
          return false;
        }
        break;
      case DexAnnotation.VISIBILITY_BUILD:
        if (!keep.runtimeInvisibleParameterAnnotations) {
          return false;
        }
        break;
      default:
        throw new Unreachable("Unexpected annotation visibility.");
    }
    return isAnnotationTypeLive(annotation);
  }

  public AnnotationRemover ensureValid(ProguardConfiguration.Builder compatibility) {
    keep.ensureValid(appView.options().forceProguardCompatibility, compatibility);
    return this;
  }

  private static boolean hasGenericEnclosingClass(
      DexProgramClass clazz,
      Map<DexType, DexProgramClass> enclosingClasses,
      Set<DexProgramClass> genericClasses) {
    while (true) {
      DexProgramClass enclosingClass = enclosingClasses.get(clazz.type);
      if (enclosingClass == null) {
        return false;
      }
      if (genericClasses.contains(enclosingClass)) {
        return true;
      }
      clazz = enclosingClass;
    }
  }

  private static boolean hasSignatureAnnotation(DexProgramClass clazz, DexItemFactory itemFactory) {
    for (DexAnnotation annotation : clazz.annotations.annotations) {
      if (DexAnnotation.isSignatureAnnotation(annotation, itemFactory)) {
        return true;
      }
    }
    return false;
  }

  public static Set<DexType> computeClassesToRetainInnerClassAttributeFor(
      AppView<? extends AppInfoWithLiveness> appView) {
    // In case of minification for certain inner classes we need to retain their InnerClass
    // attributes because their minified name still needs to be in hierarchical format
    // (enclosing$inner) otherwise the GenericSignatureRewriter can't produce the correct,
    // renamed signature.

    // More precisely:
    // - we're going to retain the InnerClass attribute that refers to the same class as 'inner'
    // - for live, inner, nonstatic classes
    // - that are enclosed by a class with a generic signature.

    // In compat mode we always keep all InnerClass attributes (if requested).
    // If not requested we never keep any. In these cases don't compute eligible classes.
    if (appView.options().forceProguardCompatibility
        || !appView.options().getProguardConfiguration().getKeepAttributes().innerClasses) {
      return Collections.emptySet();
    }

    // Build lookup table and set of the interesting classes.
    // enclosingClasses.get(clazz) gives the enclosing class of 'clazz'
    Map<DexType, DexProgramClass> enclosingClasses = new IdentityHashMap<>();
    Set<DexProgramClass> genericClasses = Sets.newIdentityHashSet();

    Iterable<DexProgramClass> programClasses = appView.appInfo().classes();
    for (DexProgramClass clazz : programClasses) {
      if (hasSignatureAnnotation(clazz, appView.dexItemFactory())) {
        genericClasses.add(clazz);
      }
      for (InnerClassAttribute innerClassAttribute : clazz.getInnerClasses()) {
        if ((innerClassAttribute.getAccess() & Constants.ACC_STATIC) == 0
            && innerClassAttribute.getOuter() == clazz.type) {
          enclosingClasses.put(innerClassAttribute.getInner(), clazz);
        }
      }
    }

    Set<DexType> result = Sets.newIdentityHashSet();
    for (DexProgramClass clazz : programClasses) {
      // If [clazz] is mentioned by a keep rule, it could be used for reflection, and we therefore
      // need to keep the enclosing method and inner classes attributes, if requested.
      if (appView.appInfo().isPinned(clazz.type)) {
        for (InnerClassAttribute innerClassAttribute : clazz.getInnerClasses()) {
          DexType inner = innerClassAttribute.getInner();
          if (appView.appInfo().isNonProgramTypeOrLiveProgramType(inner)) {
            result.add(inner);
          }
          DexType context = innerClassAttribute.getLiveContext(appView.appInfo());
          if (context != null && appView.appInfo().isNonProgramTypeOrLiveProgramType(context)) {
            result.add(context);
          }
        }
      }
      if (clazz.getInnerClassAttributeForThisClass() != null
          && appView.appInfo().isNonProgramTypeOrLiveProgramType(clazz.type)
          && hasGenericEnclosingClass(clazz, enclosingClasses, genericClasses)) {
        result.add(clazz.type);
      }
    }
    return result;
  }

  public void run() {
    for (DexProgramClass clazz : appView.appInfo().classes()) {
      stripAttributes(clazz);
      clazz.annotations = clazz.annotations.rewrite(this::rewriteAnnotation);
      clazz.forEachMethod(this::processMethod);
      clazz.forEachField(this::processField);
    }
  }

  private void processMethod(DexEncodedMethod method) {
    method.annotations = method.annotations.rewrite(this::rewriteAnnotation);
    method.parameterAnnotationsList =
        method.parameterAnnotationsList.keepIf(this::filterParameterAnnotations);
  }

  private void processField(DexEncodedField field) {
    field.annotations = field.annotations.rewrite(this::rewriteAnnotation);
  }

  private DexAnnotation rewriteAnnotation(DexAnnotation original) {
    // Check if we should keep this annotation first.
    if (!filterAnnotations(original)) {
      return null;
    }
    // Then, filter out values that refer to dead definitions.
    return original.rewrite(this::rewriteEncodedAnnotation);
  }

  private DexEncodedAnnotation rewriteEncodedAnnotation(DexEncodedAnnotation original) {
    GraphLense graphLense = appView.graphLense();
    DexType annotationType = original.type.toBaseType(appView.dexItemFactory());
    DexType rewrittenType = graphLense.lookupType(annotationType);
    DexEncodedAnnotation rewrite =
        original.rewrite(
            graphLense::lookupType, element -> rewriteAnnotationElement(rewrittenType, element));
    assert rewrite != null;
    DexClass annotationClass = appView.definitionFor(rewrittenType);
    assert annotationClass == null
        || appView.appInfo().isNonProgramTypeOrLiveProgramType(rewrittenType);
    return rewrite;
  }

  private DexAnnotationElement rewriteAnnotationElement(
      DexType annotationType, DexAnnotationElement original) {
    DexClass definition = appView.definitionFor(annotationType);
    // TODO(b/73102187): How to handle annotations without definition.
    if (definition == null) {
      return original;
    }
    assert definition.isInterface();
    boolean liveGetter =
        definition.virtualMethods().stream()
            .anyMatch(method -> method.method.name == original.name);
    return liveGetter ? original : null;
  }

  private boolean enclosingMethodPinned(DexClass clazz) {
    return clazz.getEnclosingMethod() != null
        && clazz.getEnclosingMethod().getEnclosingClass() != null
        && appView.appInfo().isPinned(clazz.getEnclosingMethod().getEnclosingClass());
  }

  private static boolean hasInnerClassesFromSet(DexProgramClass clazz, Set<DexType> innerClasses) {
    for (InnerClassAttribute attr : clazz.getInnerClasses()) {
      if (attr.getOuter() == clazz.type && innerClasses.contains(attr.getInner())) {
        return true;
      }
    }
    return false;
  }

  private void stripAttributes(DexProgramClass clazz) {
    // If [clazz] is mentioned by a keep rule, it could be used for reflection, and we therefore
    // need to keep the enclosing method and inner classes attributes, if requested. In Proguard
    // compatibility mode we keep these attributes independent of whether the given class is kept.
    // To ensure reflection from both inner to outer and and outer to inner for kept classes - even
    // if only one side is kept - keep the attributes is any class mentioned in these attributes
    // is kept.
    boolean keptAnyway =
        appView.appInfo().isPinned(clazz.type)
            || enclosingMethodPinned(clazz)
            || appView.options().forceProguardCompatibility;
    boolean keepForThisInnerClass = false;
    boolean keepForThisEnclosingClass = false;
    if (!keptAnyway) {
      keepForThisInnerClass = classesToRetainInnerClassAttributeFor.contains(clazz.type);
      keepForThisEnclosingClass =
          hasInnerClassesFromSet(clazz, classesToRetainInnerClassAttributeFor);
    }
    if (keptAnyway || keepForThisInnerClass || keepForThisEnclosingClass) {
      if (!keep.enclosingMethod) {
        clazz.clearEnclosingMethod();
      }
      if (!keep.innerClasses) {
        clazz.clearInnerClasses();
      } else if (!keptAnyway) {
        // We're keeping this only because of classesToRetainInnerClassAttributeFor.
        final boolean finalKeepForThisInnerClass = keepForThisInnerClass;
        final boolean finalKeepForThisEnclosingClass = keepForThisEnclosingClass;
        clazz.removeInnerClasses(
            ica -> {
              if (appView.appInfo().isPinned(ica.getInner())) {
                return false;
              }
              if (appView.appInfo().isPinned(ica.getOuter())) {
                return false;
              }
              if (finalKeepForThisInnerClass && ica.getInner() == clazz.type) {
                return false;
              }
              if (finalKeepForThisEnclosingClass
                  && ica.getOuter() == clazz.type
                  && classesToRetainInnerClassAttributeFor.contains(ica.getInner())) {
                return false;
              }
              return true;
            });
      }
    } else {
      // These attributes are only relevant for reflection, and this class is not used for
      // reflection. (Note that clearing these attributes can enable more vertical class merging.)
      clazz.clearEnclosingMethod();
      clazz.clearInnerClasses();
    }
  }

  public static void clearAnnotations(AppView<?> appView) {
    for (DexProgramClass clazz : appView.appInfo().classes()) {
      clazz.annotations = DexAnnotationSet.empty();
      for (DexEncodedMethod method : clazz.methods()) {
        method.annotations = DexAnnotationSet.empty();
      }
      for (DexEncodedField field : clazz.fields()) {
        field.annotations = DexAnnotationSet.empty();
      }
    }
  }
}
