// 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.errors.CompilationError;
import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;

/**
 * Calculate the list of classes required in the main dex to allow legacy multidex loading.
 * Classes required in the main dex are:
 * <li> The classes with code executed before secondary dex files are installed.
 * <li> The "direct dependencies" of those classes, ie the classes required by dexopt.
 * <li> Annotation classes with a possible enum value and all classes annotated by them.
 */
public class MainDexListBuilder {

  private final Set<DexType> roots;
  private final AppView<? extends AppInfoWithClassHierarchy> appView;
  private final Map<DexType, Boolean> annotationTypeContainEnum;
  private final MainDexInfo.Builder mainDexInfoBuilder;

  public static void checkForAssumedLibraryTypes(AppInfo appInfo) {
    DexClass enumType = appInfo.definitionFor(appInfo.dexItemFactory().enumType);
    if (enumType == null) {
      throw new CompilationError("Tracing for legacy multi dex is not possible without all"
          + " classpath libraries (java.lang.Enum is missing)");
    }
    DexClass annotationType = appInfo.definitionFor(appInfo.dexItemFactory().annotationType);
    if (annotationType == null) {
      throw new CompilationError("Tracing for legacy multi dex is not possible without all"
          + " classpath libraries (java.lang.annotation.Annotation is missing)");
    }
  }

  /**
   * @param roots Classes which code may be executed before secondary dex files loading.
   * @param appView the dex appplication.
   */
  public MainDexListBuilder(
      AppView<? extends AppInfoWithClassHierarchy> appView,
      Set<DexType> roots,
      MainDexInfo.Builder mainDexInfoBuilder) {
    this.appView = appView;
    // Only consider program classes for the root set.
    assert roots.stream().allMatch(type -> appView.definitionFor(type).isProgramClass());
    this.roots = roots;
    this.mainDexInfoBuilder = mainDexInfoBuilder;
    annotationTypeContainEnum = new IdentityHashMap<>();
  }

  private AppInfoWithClassHierarchy appInfo() {
    return appView.appInfo();
  }

  public void run() {
    traceMainDexDirectDependencies();
    traceRuntimeAnnotationsWithEnumForMainDex();
  }

  private void traceRuntimeAnnotationsWithEnumForMainDex() {
    for (DexProgramClass clazz : appInfo().classes()) {
      if (mainDexInfoBuilder.contains(clazz)) {
        continue;
      }
      DexType dexType = clazz.type;
      if (isAnnotation(dexType) && isAnnotationWithEnum(dexType)) {
        if (isVisibleAnnotation(clazz)) {
          addAnnotationsWithEnum(clazz);
        }
        continue;
      }
      // Classes with annotations must be in the same dex file as the annotation. As all
      // annotations with enums goes into the main dex, move annotated classes there as well.
      clazz.forEachAnnotation(
          annotation -> {
            if (!mainDexInfoBuilder.contains(clazz)
                && annotation.visibility == DexAnnotation.VISIBILITY_RUNTIME
                && isAnnotationWithEnum(annotation.annotation.type)) {
              // Just add classes annotated with annotations with enum as direct dependencies.
              mainDexInfoBuilder.addDependency(clazz);
            }
          });
    }
  }

  private boolean isVisibleAnnotation(DexProgramClass clazz) {
    if (retainCompileTimeAnnotation(clazz.type)) {
      return true;
    }
    DexAnnotation retentionAnnotation =
        clazz.annotations().getFirstMatching(appView.dexItemFactory().retentionType);
    // Default is CLASS retention
    if (retentionAnnotation == null) {
      return false;
    }
    return retentionAnnotation.annotation.toString().contains("RUNTIME");
  }

  private boolean retainCompileTimeAnnotation(DexType type) {
    return DexAnnotation.retainCompileTimeAnnotation(type, appView.options());
  }

  private boolean isAnnotationWithEnum(DexType dexType) {
    Boolean value = annotationTypeContainEnum.get(dexType);
    if (value == null) {
      DexClass clazz = appView.definitionFor(dexType);
      if (clazz == null) {
        // Information is missing lets be conservative.
        value = true;
      } else {
        value = false;
        // Browse annotation values types in search for enum.
        // Each annotation value is represented by a virtual method.
        for (DexEncodedMethod method : clazz.virtualMethods()) {
          DexProto proto = method.getReference().proto;
          if (proto.parameters.isEmpty()) {
            DexType valueType = proto.returnType.toBaseType(appView.dexItemFactory());
            if (valueType.isClassType()) {
              assert !value;
              boolean notLibraryOrTakeBootClasspath =
                  !appInfo().definitionFor(valueType).isLibraryClass()
                      || !appView.options().ignoreBootClasspathEnumsForMaindexTracing;
              value =
                  (isEnum(valueType) && notLibraryOrTakeBootClasspath)
                      || (isAnnotation(valueType) && isAnnotationWithEnum(valueType));
            }
          }
          if (value) {
            break;
          }
        }
      }
      annotationTypeContainEnum.put(dexType, value);
    }
    return value;
  }

  private boolean isEnum(DexType valueType) {
    return valueType.isClassType()
        && appInfo().isSubtype(valueType, appView.dexItemFactory().enumType);
  }

  private boolean isAnnotation(DexType valueType) {
    return appInfo().isSubtype(valueType, appView.dexItemFactory().annotationType);
  }

  private void traceMainDexDirectDependencies() {
    new MainDexDirectReferenceTracer(appView, this::addDirectDependency).run(roots);
  }

  private void addAnnotationsWithEnum(DexProgramClass clazz) {
    // Add the annotation class as a direct dependency.
    addDirectDependency(clazz);
    // Add enum classes used for values as direct dependencies.
    for (DexEncodedMethod method : clazz.virtualMethods()) {
      DexProto proto = method.getReference().proto;
      if (proto.parameters.isEmpty()) {
        DexType valueType = proto.returnType.toBaseType(appView.dexItemFactory());
        if (isEnum(valueType)) {
          addDirectDependency(valueType);
        }
      }
    }
  }

  private void addDirectDependency(DexType type) {
    // Consider only component type of arrays
    type = type.toBaseType(appView.dexItemFactory());
    if (!type.isClassType() || mainDexInfoBuilder.contains(type)) {
      return;
    }

    DexClass clazz = appView.definitionFor(type);
    // No library classes in main-dex.
    if (clazz == null || clazz.isNotProgramClass()) {
      return;
    }
    addDirectDependency(clazz.asProgramClass());
  }

  private void addDirectDependency(DexProgramClass dexClass) {
    assert !mainDexInfoBuilder.contains(dexClass);
    mainDexInfoBuilder.addDependency(dexClass);
    if (dexClass.superType != null) {
      addDirectDependency(dexClass.superType);
    }
    for (DexType interfaze : dexClass.interfaces.values) {
      addDirectDependency(interfaze);
    }
  }
}
