// Copyright (c) 2021, 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.utils;

import static com.android.tools.r8.graph.DexLibraryClass.asLibraryClassOrNull;

import com.android.tools.r8.androidapi.AndroidApiLevelCompute;
import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMember;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.LibraryClass;
import com.android.tools.r8.graph.LibraryDefinition;
import com.android.tools.r8.graph.LibraryMethod;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.optimize.inliner.NopWhyAreYouNotInliningReporter;
import com.android.tools.r8.ir.optimize.inliner.WhyAreYouNotInliningReporter;
import com.google.common.collect.Sets;
import java.util.Collections;
import java.util.Set;

public class AndroidApiLevelUtils {

  public static boolean isApiSafeForInlining(
      ProgramMethod caller, ProgramMethod inlinee, InternalOptions options) {
    return isApiSafeForInlining(
        caller, inlinee, options, NopWhyAreYouNotInliningReporter.getInstance());
  }

  @SuppressWarnings("ReferenceEquality")
  public static boolean isApiSafeForInlining(
      ProgramMethod caller,
      ProgramMethod inlinee,
      InternalOptions options,
      WhyAreYouNotInliningReporter whyAreYouNotInliningReporter) {
    if (!options.apiModelingOptions().isApiCallerIdentificationEnabled()) {
      return true;
    }
    if (caller.getHolderType() == inlinee.getHolderType()) {
      return true;
    }
    ComputedApiLevel callerApiLevelForCode = caller.getDefinition().getApiLevelForCode();
    if (callerApiLevelForCode.isUnknownApiLevel()) {
      whyAreYouNotInliningReporter.reportCallerHasUnknownApiLevel();
      return false;
    }
    // For inlining we only measure if the code has invokes into the library.
    ComputedApiLevel inlineeApiLevelForCode = inlinee.getDefinition().getApiLevelForCode();
    if (!caller
        .getDefinition()
        .getApiLevelForCode()
        .isGreaterThanOrEqualTo(inlineeApiLevelForCode)) {
      whyAreYouNotInliningReporter.reportInlineeHigherApiCall(
          callerApiLevelForCode, inlineeApiLevelForCode);
      return false;
    }
    return true;
  }

  public static ComputedApiLevel getApiReferenceLevelForMerging(
      AndroidApiLevelCompute apiLevelCompute, DexProgramClass clazz) {
    // The api level of a class is the max level of it's members, super class and interfaces.
    return getMembersApiReferenceLevelForMerging(
        clazz, apiLevelCompute.computeApiLevelForDefinition(clazz.allImmediateSupertypes()));
  }

  public static ComputedApiLevel getMembersApiReferenceLevelForMerging(
      DexProgramClass clazz, ComputedApiLevel memberLevel) {
    // Based on b/138781768#comment57 there is almost no penalty for having an unknown reference
    // as long as we are not invoking or accessing a field on it. Therefore we can disregard static
    // types of fields and only consider method code api levels.
    for (DexEncodedMethod method : clazz.methods()) {
      if (method.hasCode()) {
        ComputedApiLevel apiLevelForCode = method.getApiLevelForCode();
        if (apiLevelForCode.isNotSetApiLevel()) {
          return ComputedApiLevel.notSet();
        }
        memberLevel = memberLevel.max(apiLevelForCode);
      }
      if (memberLevel.isUnknownApiLevel()) {
        return memberLevel;
      }
    }
    return memberLevel;
  }

  public static boolean isApiSafeForMemberRebinding(
      LibraryMethod method,
      DexMethod original,
      AndroidApiLevelCompute androidApiLevelCompute,
      InternalOptions options) {
    if (!androidApiLevelCompute.isEnabled()) {
      assert !options.apiModelingOptions().enableLibraryApiModeling;
      return false;
    }
    assert options.apiModelingOptions().enableLibraryApiModeling;
    ComputedApiLevel apiLevel =
        androidApiLevelCompute.computeApiLevelForLibraryReference(
            method.getReference(), ComputedApiLevel.unknown());
    if (apiLevel.isUnknownApiLevel()) {
      return false;
    }
    ComputedApiLevel apiLevelOfOriginal =
        androidApiLevelCompute.computeApiLevelForLibraryReference(
            original, ComputedApiLevel.unknown());
    if (apiLevelOfOriginal.isUnknownApiLevel()) {
      return false;
    }
    return apiLevelOfOriginal.max(apiLevel).isLessThanOrEqualTo(options.getMinApiLevel()).isTrue();
  }

  public static boolean isApiSafeForReference(LibraryDefinition definition, AppView<?> appView) {
    return isApiSafeForReference(
        definition, appView.apiLevelCompute(), appView.options(), appView.dexItemFactory());
  }

  @SuppressWarnings("ReferenceEquality")
  private static boolean isApiSafeForReference(
      LibraryDefinition definition,
      AndroidApiLevelCompute androidApiLevelCompute,
      InternalOptions options,
      DexItemFactory factory) {
    if (!options.apiModelingOptions().isApiLibraryModelingEnabled()) {
      return factory.libraryTypesAssumedToBePresent.contains(definition.getContextType());
    }
    ComputedApiLevel apiLevel =
        androidApiLevelCompute.computeApiLevelForLibraryReference(
            definition.getReference(), ComputedApiLevel.unknown());
    return apiLevel.isLessThanOrEqualTo(options.getMinApiLevel()).isTrue();
  }

  private static boolean isApiSafeForReference(
      LibraryDefinition newDefinition, LibraryDefinition oldDefinition, AppView<?> appView) {
    assert appView.options().apiModelingOptions().isApiLibraryModelingEnabled();
    assert !isApiSafeForReference(newDefinition, appView)
        : "Clients should first check if the definition is present on all apis since the min api";
    AndroidApiLevelCompute androidApiLevelCompute = appView.apiLevelCompute();
    ComputedApiLevel apiLevel =
        androidApiLevelCompute.computeApiLevelForLibraryReference(
            newDefinition.getReference(), ComputedApiLevel.unknown());
    if (apiLevel.isUnknownApiLevel()) {
      return false;
    }
    ComputedApiLevel apiLevelOfOriginal =
        androidApiLevelCompute.computeApiLevelForLibraryReference(
            oldDefinition.getReference(), ComputedApiLevel.unknown());
    return apiLevel.isLessThanOrEqualTo(apiLevelOfOriginal).isTrue();
  }

  @SuppressWarnings({"MixedMutabilityReturnType", "ReferenceEquality"})
  public static boolean isApiSafeForTypeStrengthening(
      DexType newType, DexType oldType, AppView<? extends AppInfoWithClassHierarchy> appView) {
    // Type strengthening only applies to reference types.
    assert newType.isReferenceType();
    assert oldType.isReferenceType();
    assert newType != oldType;
    DexItemFactory dexItemFactory = appView.dexItemFactory();
    DexType newBaseType = newType.toBaseType(dexItemFactory);
    if (newBaseType.isPrimitiveType()) {
      // Array of primitives is available on all api levels.
      return true;
    }
    assert newBaseType.isClassType();
    DexClass newBaseClass = appView.definitionFor(newBaseType);
    if (newBaseClass == null) {
      // This could be a library class that is only available on newer api levels.
      return false;
    }
    if (!newBaseClass.isLibraryClass()) {
      // Program and classpath classes are not api level dependent.
      return true;
    }
    if (!appView.options().apiModelingOptions().isApiLibraryModelingEnabled()) {
      // Conservatively bail out if we don't have api modeling.
      return false;
    }
    LibraryClass newBaseLibraryClass = newBaseClass.asLibraryClass();
    if (isApiSafeForReference(newBaseLibraryClass, appView)) {
      // Library class is present on all api levels since min api.
      return true;
    }
    // Check if the new library class is present since the api level of the old type.
    DexType oldBaseType = oldType.toBaseType(dexItemFactory);
    assert oldBaseType.isClassType();
    LibraryClass oldBaseLibraryClass = asLibraryClassOrNull(appView.definitionFor(oldBaseType));
    return oldBaseLibraryClass != null
        && isApiSafeForReference(newBaseLibraryClass, oldBaseLibraryClass, appView);
  }

  public static Pair<DexClass, ComputedApiLevel> findAndComputeApiLevelForLibraryDefinition(
      AppView<?> appView,
      AppInfoWithClassHierarchy appInfo,
      DexClass holder,
      DexMember<?, ?> reference) {
    AndroidApiLevelCompute apiLevelCompute = appView.apiLevelCompute();
    if (holder.isLibraryClass()) {
      return Pair.create(
          holder,
          apiLevelCompute.computeApiLevelForLibraryReference(
              reference, ComputedApiLevel.unknown()));
    }
    // The API database do not allow for resolving into it (since that is not stable), and it is
    // therefore designed in a way where all members of classes can be queried on any sub-type with
    // the api level for where it is reachable. It is therefore sufficient for us, to figure out if
    // an instruction is a library call, to either find a program definition or to find the library
    // frontier.
    // Scan through the type hierarchy to find the first library class or program definition.
    DexClass firstClassWithReferenceOrLibraryClass =
        firstLibraryClassOrProgramClassWithDefinition(appInfo, holder, reference);
    if (firstClassWithReferenceOrLibraryClass == null) {
      return Pair.create(null, ComputedApiLevel.unknown());
    }
    if (!firstClassWithReferenceOrLibraryClass.isLibraryClass()) {
      return Pair.create(firstClassWithReferenceOrLibraryClass, appView.computedMinApiLevel());
    }
    ComputedApiLevel apiLevel =
        apiLevelCompute.computeApiLevelForLibraryReference(
            reference.withHolder(
                firstClassWithReferenceOrLibraryClass.getType(), appView.dexItemFactory()),
            ComputedApiLevel.unknown());
    if (apiLevel.isKnownApiLevel()) {
      return Pair.create(firstClassWithReferenceOrLibraryClass, apiLevel);
    }
    // We were unable to find a definition in the class hierarchy, check all interfaces for a
    // definition or the library interfaces for the first interface definition.
    Set<DexClass> firstLibraryInterfaces =
        findAllFirstLibraryInterfacesOrProgramClassWithDefinition(appInfo, holder, reference);
    if (firstLibraryInterfaces.size() == 1) {
      DexClass firstClass = firstLibraryInterfaces.iterator().next();
      if (!firstClass.isLibraryClass()) {
        return Pair.create(firstClass, appView.computedMinApiLevel());
      }
    }
    DexClass foundClass = null;
    ComputedApiLevel minApiLevel = ComputedApiLevel.unknown();
    for (DexClass libraryInterface : firstLibraryInterfaces) {
      assert libraryInterface.isLibraryClass();
      ComputedApiLevel libraryIfaceApiLevel =
          apiLevelCompute.computeApiLevelForLibraryReference(
              reference.withHolder(
                  firstClassWithReferenceOrLibraryClass.getType(), appView.dexItemFactory()),
              ComputedApiLevel.unknown());
      if (minApiLevel.isGreaterThan(libraryIfaceApiLevel)) {
        minApiLevel = libraryIfaceApiLevel;
        foundClass = libraryInterface;
      }
    }
    return Pair.create(foundClass, minApiLevel);
  }

  private static DexClass firstLibraryClassOrProgramClassWithDefinition(
      AppInfoWithClassHierarchy appInfo, DexClass originalClass, DexMember<?, ?> reference) {
    if (originalClass.isLibraryClass()) {
      return originalClass;
    }
    return WorkList.newIdentityWorkList(originalClass)
        .run(
            (clazz, workList) -> {
              if (clazz.isLibraryClass()) {
                return TraversalContinuation.doBreak(clazz);
              } else if (clazz.lookupMember(reference) != null) {
                return TraversalContinuation.doBreak(clazz);
              } else if (clazz.getSuperType() != null) {
                appInfo
                    .contextIndependentDefinitionForWithResolutionResult(clazz.getSuperType())
                    .forEachClassResolutionResult(workList::addIfNotSeen);
              }
              return TraversalContinuation.doContinue();
            })
        .asBreakOrDefault(null)
        .getValue();
  }

  @SuppressWarnings("MixedMutabilityReturnType")
  private static Set<DexClass> findAllFirstLibraryInterfacesOrProgramClassWithDefinition(
      AppInfoWithClassHierarchy appInfo, DexClass originalClass, DexMember<?, ?> reference) {
    Set<DexClass> interfaces = Sets.newLinkedHashSet();
    WorkList<DexClass> workList = WorkList.newIdentityWorkList(originalClass);
    while (workList.hasNext()) {
      DexClass clazz = workList.next();
      if (clazz.isLibraryClass()) {
        if (clazz.isInterface()) {
          interfaces.add(clazz);
        }
      } else if (clazz.lookupMember(reference) != null) {
        return Collections.singleton(clazz);
      } else {
        clazz.forEachImmediateSupertype(
            superType ->
                appInfo
                    .contextIndependentDefinitionForWithResolutionResult(superType)
                    .forEachClassResolutionResult(workList::addIfNotSeen));
      }
    }
    return interfaces;
  }

  /**
   * A lot of functionality has already been outlined in androidx. The ordinary pattern for manual
   * outlining is to create a class with the name ApiXXImpl where XX is the api level. This method
   * will check the context to see if it matches this pattern in androidx and extract the api level
   * for comparison with the computed api level.
   */
  public static boolean isOutlinedAtSameOrLowerLevel(
      DexProgramClass clazz, ComputedApiLevel apiLevel) {
    assert apiLevel.isKnownApiLevel();
    if (!clazz.getType().getDescriptor().startsWith("Landroidx/")) {
      return false;
    }
    String simpleName = clazz.getSimpleName();
    int apiIndex = simpleName.indexOf("Api");
    if (apiIndex < 0) {
      return false;
    }
    int endApiIndex = apiIndex += 3;
    int implIndex = simpleName.indexOf("Impl");
    if (implIndex < 0 || implIndex < endApiIndex || (implIndex - endApiIndex) != 2) {
      return false;
    }
    String apiLevelAsString = simpleName.substring(endApiIndex, implIndex);
    if (!StringUtils.onlyContainsDigits(apiLevelAsString)) {
      return false;
    }
    int apiLevelAsInt = Integer.parseInt(apiLevelAsString);
    if (apiLevelAsInt < 10 || apiLevelAsInt > AndroidApiLevel.LATEST.getLevel()) {
      return false;
    }
    return apiLevel.asKnownApiLevel().getApiLevel().getLevel() <= apiLevelAsInt;
  }

  public static boolean isApiLevelLessThanOrEqualToG(ComputedApiLevel apiLevel) {
    return apiLevel.isKnownApiLevel()
        && apiLevel.asKnownApiLevel().getApiLevel().isLessThanOrEqualTo(AndroidApiLevel.G);
  }
}
