// 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.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.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
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";

  // A list of self-contained jars to process (which do not depend on other jar files).
  private static final List<Pair<Path, Predicate<Version>>> LIST_OF_JARS = new ConfigListBuilder()
      .add(DebugTestBase.DEBUGGEE_JAR, ContinuousSteppingTest::allVersions)
      .add(DebugTestBase.DEBUGGEE_JAVA8_JAR, ContinuousSteppingTest::allVersions)
      .add(KotlinD8Config.DEBUGGEE_KOTLIN_JAR, 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 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();
    }
  }

  @BeforeClass
  public static void setup() {
    LIST_OF_JARS.forEach(pair -> {
      if (pair.getSecond().test(ToolHelper.getDexVm().getVersion())) {
        Path jarPath = pair.getFirst();
        DebugTestConfig config = new D8DebugTestConfig().compileAndAdd(temp, jarPath);
        compiledJarConfig.put(jarPath, config);
      }
    });
  }

  @Parameters(name = "{0} from {1}")
  public static Collection<Object[]> getData() throws IOException {
    List<Object[]> testCases = new ArrayList<>();
    for (Pair<Path, Predicate<Version>> pair : LIST_OF_JARS) {
      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});
        }
      }
    }
    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;
        }));
  }

}
