// 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.debug;

import com.android.tools.r8.KotlinTestParameters;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.ToolHelper;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.Pair;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
import java.util.stream.Collectors;
import org.apache.harmony.jpda.tests.framework.jdwp.Value;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(Parameterized.class)
public class ContinuousSteppingTest extends DebugTestBase {

  private static final String MAIN_METHOD_NAME = "main";

  private static final TemporaryFolder testTemp = ToolHelper.getTemporaryFolderForTest();

  // A list of self-contained jars to process (which do not depend on other jar files).
  private static List<Pair<Path, Predicate<Version>>> listOfJars() {
    return new ConfigListBuilder()
        .add(DebugTestBase.DEBUGGEE_JAR, ContinuousSteppingTest::allVersions)
        .add(DebugTestBase.DEBUGGEE_JAVA8_JAR, ContinuousSteppingTest::allVersions)
        .addAllKotlinDebugJars(testTemp, ContinuousSteppingTest::allVersions)
        .addAll(
            findAllJarsIn(Paths.get(ToolHelper.EXAMPLES_ANDROID_N_BUILD_DIR)),
            ContinuousSteppingTest::fromAndroidN)
        // TODO(b/79911828) Investigate timeout issues for Android O examples.
        //  .addAll(findAllJarsIn(Paths.get(ToolHelper.EXAMPLES_ANDROID_O_BUILD_DIR)),
        //      ContinuousSteppingTest::fromAndroidO)
        .build();
  }

  private static final Map<Path, DebugTestConfig> compiledJarConfig = new HashMap<>();

  private final String mainClass;
  private final Path jarPath;

  private static class ConfigListBuilder {

    private final Builder<Pair<Path, Predicate<Version>>> builder = ImmutableList.builder();

    public ConfigListBuilder add(Path path, Predicate<Version> predicate) {
      builder.add(new Pair<>(path, predicate));
      return this;
    }

    public ConfigListBuilder addAll(List<Path> paths, Predicate<Version> predicate) {
      for (Path path : paths) {
        add(path, predicate);
      }
      return this;
    }

    public ConfigListBuilder addAllKotlinDebugJars(
        TemporaryFolder temp, Predicate<Version> predicate) {
      for (KotlinTestParameters kotlinParameter :
          TestBase.getKotlinTestParameters().withAllCompilersAndTargetVersions().build()) {
        add(KotlinD8Config.compileKotlinMemoized.apply(temp, kotlinParameter), predicate);
      }
      return this;
    }

    public List<Pair<Path, Predicate<Version>>> build() {
      return builder.build();
    }
  }

  public static boolean allVersions(Version dexVmVersion) {
    return true;
  }

  public static boolean fromAndroidN(Version dexVmVersion) {
    return dexVmVersion.isAtLeast(Version.V7_0_0);
  }

  private static List<Path> findAllJarsIn(Path root) {
    try {
      return Files.walk(root)
          .filter(p -> p.toFile().getPath().endsWith(FileUtils.JAR_EXTENSION))
          .collect(Collectors.toList());
    } catch (IOException e) {
      return Collections.emptyList();
    }
  }

  @AfterClass
  public static void tearDown() {
    testTemp.delete();
  }

  @Parameters(name = "{0} from {1}")
  public static Collection<Object[]> getData() throws IOException {
    testTemp.create();
    List<Object[]> testCases = new ArrayList<>();
    for (Pair<Path, Predicate<Version>> pair : listOfJars()) {
      if (pair.getSecond().test(ToolHelper.getDexVm().getVersion())) {
        Path jarPath = pair.getFirst();
        List<String> mainClasses = getAllMainClassesFromJar(jarPath);
        for (String className : mainClasses) {
          testCases.add(new Object[]{className, jarPath});
        }

        DebugTestConfig config = new D8DebugTestConfig().compileAndAdd(testTemp, jarPath);
        compiledJarConfig.put(jarPath, config);
      }
    }
    return testCases;
  }

  public ContinuousSteppingTest(String mainClass, Path jarPath) {
    this.mainClass = mainClass;
    this.jarPath = jarPath;
  }

  @Test
  public void testContinuousSingleStep() throws Throwable {
    assert compiledJarConfig.containsKey(jarPath);
    DebugTestConfig config = compiledJarConfig.get(jarPath);
    assert config != null;
    runContinuousTest(mainClass, config);
  }

  // Returns a list of classes with a "public static void main(String[])" method in the given jar
  // file.
  private static List<String> getAllMainClassesFromJar(Path pathToJar) throws IOException {
    JarInputStream jarInputStream = new JarInputStream(Files.newInputStream(pathToJar,
        StandardOpenOption.READ));
    final URL url = pathToJar.toUri().toURL();
    assert pathToJar.toFile().exists();
    assert pathToJar.toFile().isFile();
    List<String> mainClasses = new ArrayList<>();
    ClassLoader loader = new URLClassLoader(new URL[]{url},
        Thread.currentThread().getContextClassLoader());

    try {
      JarEntry entry;
      while ((entry = jarInputStream.getNextJarEntry()) != null) {
        String entryName = entry.getName();
        if (entryName.endsWith(FileUtils.CLASS_EXTENSION)) {
          String className =
              entryName.substring(0, entryName.length() - FileUtils.CLASS_EXTENSION.length());
          className = className.replace(DescriptorUtils.DESCRIPTOR_PACKAGE_SEPARATOR,
              DescriptorUtils.JAVA_PACKAGE_SEPARATOR);
          try {
            Class<?> cls = loader.loadClass(className);
            if (cls != null) {
              long mainMethodsCount = Arrays.stream(cls.getMethods())
                  .filter(ContinuousSteppingTest::isMainMethod)
                  .count();
              if (mainMethodsCount == 1) {
                // Add class to the list
                mainClasses.add(className);
              }
            }
          } catch (Throwable e) {
            System.out.println(
                "Could not load class " + className + " from " + pathToJar.toFile().getPath());
            return Collections.emptyList();
          }
        }
      }
    } finally {
      jarInputStream.close();
    }
    return mainClasses;
  }

  private static boolean isMainMethod(Method m) {
    return Modifier.isStatic(m.getModifiers())
        && m.getReturnType() == void.class
        && m.getName().equals(MAIN_METHOD_NAME)
        && m.getParameterCount() == 1
        && m.getParameterTypes()[0] == String[].class;
  }

  private void runContinuousTest(String debuggeeClassName, DebugTestConfig config)
      throws Throwable {
    runDebugTest(
        config,
        debuggeeClassName,
        breakpoint(debuggeeClassName, MAIN_METHOD_NAME),
        run(),
        stepUntil(StepKind.OVER, StepLevel.INSTRUCTION, debuggeeState -> {
          // Fetch local variables.
          Map<String, Value> localValues = debuggeeState.getLocalValues();
          Assert.assertNotNull(localValues);

          // Always step until we actually exit the program.
          return false;
        }));
  }

}
