// 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.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 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(10, toSuper.size());
    Assert.assertEquals(11, classIntroducedBeforeClose.size());
    Assert.assertEquals(5, closeBackports.size());

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

  private void print(
      List<DexMethod> closeBackports,
      Map<DexType, AndroidApiLevel> classIntroducedBeforeClose,
      Map<DexType, DexType> toSuper) {
    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(type + " ");
          if (toSub.containsKey(type)) {
            System.out.print("[");
            for (DexType sub : toSub.get(type)) {
              System.out.print(sub + ", ");
            }
            System.out.print("] ");
          }
          if (closeBackports.stream().anyMatch(m -> m.getHolderType() == type)) {
            System.out.print("-- backport");
          }
          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.getTypeRewriter(), Timing.empty());
  }
}
