// Copyright (c) 2024, 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 twr;

import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.dex.ApplicationReader;
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.DexClass;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexItemFactory;
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.DirectMappedDexApplication;
import com.android.tools.r8.ir.desugar.BackportedMethodRewriter;
import com.android.tools.r8.synthesis.SyntheticItems.GlobalSyntheticsStrategy;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.OptionalBool;
import com.android.tools.r8.utils.Timing;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.io.IOException;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class LookUpCloseResourceTest extends TestBase {

  private static final Set<String> CANNOT_FIX =
      ImmutableSet.of(
          "java.net.URLClassLoader",
          "android.net.wifi.p2p.WifiP2pManager$Channel",
          "android.content.res.AssetFileDescriptor$AutoCloseInputStream");
  private static final Set<String> TOO_OLD_TO_FIX =
      ImmutableSet.of("java.nio.channels.FileLock", "android.database.sqlite.SQLiteClosable");
  private static final boolean DEBUG_PRINT = false;
  private static int MAX_PROCESSED_ANDROID_API_LEVEL = 36;

  @Parameter public TestParameters parameters;

  @Parameters(name = "{0}")
  public static TestParametersCollection data() {
    return getTestParameters().withNoneRuntime().build();
  }

  @Test
  public void test() throws Exception {
    InternalOptions options = new InternalOptions();
    options
        .getArtProfileOptions()
        .setAllowReadingEmptyArtProfileProvidersMultipleTimesForTesting(true);
    DexItemFactory factory = options.dexItemFactory();
    DexMethod close =
        factory.createMethod(
            factory.autoCloseableType, factory.createProto(factory.voidType), "close");

    Map<DexType, DexType> toSuper = new IdentityHashMap<>();
    AppView<?> appViewForMax = getAppInfo(options, MAX_PROCESSED_ANDROID_API_LEVEL);
    AppInfoWithClassHierarchy appInfoForMax = appViewForMax.appInfoForDesugaring();
    List<DexType> autoCloseableSubclassesWithOverride = new ArrayList<>();
    for (DexProgramClass clazz : appInfoForMax.classes()) {
      OptionalBool contains =
          appInfoForMax.implementedInterfaces(clazz.getType()).contains(factory.autoCloseableType);
      if (contains.isTrue() && clazz.getType() != factory.autoCloseableType) {
        if (clazz.lookupVirtualMethod(close.withHolder(clazz.getType(), factory)) != null) {
          autoCloseableSubclassesWithOverride.add(clazz.getType());
        } else {
          DexClassAndMethod superResult =
              appInfoForMax.lookupSuperTarget(
                  close.withHolder(clazz.getType(), factory), clazz, appViewForMax, appInfoForMax);
          if (superResult == null) {
            superResult =
                appInfoForMax.lookupMaximallySpecificMethod(
                    clazz, close.withHolder(clazz.getType(), factory));
          }
          // Abstract class/itf may directly rely on AutoCloseable#close().
          assert superResult != null || clazz.isAbstract();
          if (superResult != null) {
            toSuper.put(clazz.getType(), superResult.getHolderType());
          }
        }
      }
    }

    Map<DexType, AndroidApiLevel> classIntroducedBeforeClose = new IdentityHashMap<>();
    for (int i = MAX_PROCESSED_ANDROID_API_LEVEL - 1; i > 0; i--) {
      if (ToolHelper.hasAndroidJar(AndroidApiLevel.getAndroidApiLevel(i))) {
        AppView<?> appView = getAppInfo(options, i);
        AppInfoWithClassHierarchy appInfo = appView.appInfoForDesugaring();
        for (DexType type : autoCloseableSubclassesWithOverride) {
          DexClass clazz = appInfo.definitionFor(type);
          if (clazz != null
              && clazz.lookupVirtualMethod(close) == null
              && !classIntroducedBeforeClose.containsKey(type)) {
            classIntroducedBeforeClose.put(type, AndroidApiLevel.getAndroidApiLevel(i));
          }
        }
      }
    }

    List<DexMethod> closeBackports = new ArrayList<>();
    BackportedMethodRewriter.generateListOfBackportedMethodsAndFields(
        appInfoForMax.app(),
        options,
        m -> {
          if (m.getName().toString().equals("close")) {
            closeBackports.add(m);
          }
        },
        f -> {});

    Set<DexType> toRemove = Sets.newIdentityHashSet();
    toSuper.forEach(
        (k, v) -> {
          if (!classIntroducedBeforeClose.containsKey(v)) {
            toRemove.add(k);
          }
        });
    for (DexType dexType : toRemove) {
      toSuper.remove(dexType);
    }

    Assert.assertEquals(9, toSuper.size());
    Assert.assertEquals(12, classIntroducedBeforeClose.size());
    Assert.assertEquals(6, closeBackports.size());

    if (DEBUG_PRINT) {
      print(closeBackports, classIntroducedBeforeClose, toSuper, appViewForMax);
    }
  }

  private void print(
      List<DexMethod> closeBackports,
      Map<DexType, AndroidApiLevel> classIntroducedBeforeClose,
      Map<DexType, DexType> toSuper,
      AppView<?> appView) {
    Map<DexType, List<DexType>> toSub = new IdentityHashMap<>();
    toSuper.forEach(
        (sup, sub) -> {
          toSub.computeIfAbsent(sub, k -> new ArrayList<>()).add(sup);
        });
    System.out.println("Classes introduced in android.jar before their close() method override :");
    classIntroducedBeforeClose.forEach(
        (type, api) -> {
          System.out.print(api + " ");
          System.out.print(appView.definitionFor(type).isFinal() ? "f " : "nf ");
          System.out.print(type + " ");
          if (closeBackports.stream().anyMatch(m -> m.getHolderType() == type)) {
            System.out.print("-- backport");
          }
          if (CANNOT_FIX.contains(type.toString())) {
            System.out.print("-- cannotfix");
          }
          if (TOO_OLD_TO_FIX.contains(type.toString())) {
            System.out.print("-- tooOldToFix");
          }
          System.out.println();
          if (toSub.containsKey(type)) {
            System.out.print("[");
            for (DexType sub : toSub.get(type)) {
              System.out.print(sub + ", ");
            }
            System.out.println("] ");
          }
        });
  }

  private AppView<?> getAppInfo(InternalOptions options, int api) throws IOException {
    AndroidApp app = AndroidApp.builder().addProgramFile(ToolHelper.getAndroidJar(api)).build();
    DirectMappedDexApplication libHolder =
        new ApplicationReader(app, options, Timing.empty()).read().toDirect();
    AppInfo initialAppInfo =
        AppInfo.createInitialAppInfo(libHolder, GlobalSyntheticsStrategy.forNonSynthesizing());
    return AppView.createForD8(
        initialAppInfo, options.getLibraryDesugaringOptions().getTypeRewriter(), Timing.empty());
  }
}
