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

import static com.android.tools.r8.KotlinCompilerTool.KotlinCompilerVersion.MAX_SUPPORTED_VERSION;
import static com.android.tools.r8.ToolHelper.isWindows;
import static com.google.common.io.Files.getNameWithoutExtension;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import com.android.tools.r8.TestRuntime.CfRuntime;
import com.android.tools.r8.ToolHelper.CacheLookupKey;
import com.android.tools.r8.ToolHelper.CommandResultCache;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.utils.ArrayUtils;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.Pair;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.ThrowingConsumer;
import com.android.tools.r8.utils.structural.Ordered;
import com.google.common.hash.Hasher;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.junit.rules.TemporaryFolder;

public class KotlinCompilerTool {

  public enum KotlinTargetVersion {
    NONE(""),
    JAVA_6("JAVA_6"),
    JAVA_8("JAVA_8");

    private final String folderName;

    KotlinTargetVersion(String folderName) {
      this.folderName = folderName;
    }

    public String getFolderName() {
      return folderName;
    }

    public String getJvmTargetString() {
      switch (this) {
        case JAVA_6:
          return "1.6";
        case JAVA_8:
          return "1.8";
        default:
          throw new Unimplemented("JvmTarget not specified for " + this);
      }
    }
  }

  public enum KotlinCompilerVersion implements Ordered<KotlinCompilerVersion> {
    KOTLINC_1_3_72("kotlin-compiler-1.3.72"),
    KOTLINC_1_4_20("kotlin-compiler-1.4.20"),
    KOTLINC_1_5_0("kotlin-compiler-1.5.0"),
    KOTLINC_1_6_0("kotlin-compiler-1.6.0"),
    KOTLINC_1_7_0("kotlin-compiler-1.7.0"),
    KOTLINC_1_8_0("kotlin-compiler-1.8.0"),
    KOTLINC_1_9_21("kotlin-compiler-1.9.21"),
    KOTLIN_DEV("kotlin-compiler-dev");

    public static final KotlinCompilerVersion MIN_SUPPORTED_VERSION = KOTLINC_1_7_0;
    public static final KotlinCompilerVersion MAX_SUPPORTED_VERSION = KOTLINC_1_9_21;

    private final String folder;

    KotlinCompilerVersion(String folder) {
      this.folder = folder;
    }

    public static KotlinCompilerVersion latest() {
      return ArrayUtils.last(values());
    }

    public KotlinCompiler getCompiler() {
      return new KotlinCompiler(this);
    }

    public static List<KotlinCompilerVersion> getSupported() {
      return Arrays.stream(KotlinCompilerVersion.values())
          .filter(
              compiler ->
                  compiler.isGreaterThanOrEqualTo(MIN_SUPPORTED_VERSION)
                      && compiler.isLessThanOrEqualTo(MAX_SUPPORTED_VERSION))
          .collect(Collectors.toList());
    }
  }

  public static final class KotlinCompiler {

    private final String name;
    private final Path lib;
    private final Path compiler;
    private final KotlinCompilerVersion compilerVersion;

    public KotlinCompiler(KotlinCompilerVersion compilerVersion) {
      this.lib =
          Paths.get(ToolHelper.THIRD_PARTY_DIR, "kotlin", compilerVersion.folder, "kotlinc", "lib");
      this.compiler = lib.resolve("kotlin-compiler.jar");
      this.compilerVersion = compilerVersion;
      this.name = compilerVersion.name();
    }

    public KotlinCompiler(String name, Path compiler, KotlinCompilerVersion compilerVersion) {
      this.compiler = compiler;
      this.lib = null;
      this.compilerVersion = compilerVersion;
      this.name = name;
    }

    public static KotlinCompiler latest() {
      return MAX_SUPPORTED_VERSION.getCompiler();
    }

    public Path getCompiler() {
      return compiler;
    }

    public Path getFolder() {
      return lib;
    }

    public boolean is(KotlinCompilerVersion version) {
      return compilerVersion == version;
    }

    public boolean isOneOf(KotlinCompilerVersion... versions) {
      return Arrays.stream(versions).anyMatch(this::is);
    }

    public boolean isNot(KotlinCompilerVersion version) {
      return !is(version);
    }

    public KotlinCompilerVersion getCompilerVersion() {
      return compilerVersion;
    }

    public Path getKotlinStdlibJar() {
      Path stdLib = getFolder().resolve("kotlin-stdlib.jar");
      assert Files.exists(stdLib) : "Expected kotlin stdlib jar";
      return stdLib;
    }

    public Path getKotlinReflectJar() {
      Path reflectJar = getFolder().resolve("kotlin-reflect.jar");
      assert Files.exists(reflectJar) : "Expected kotlin reflect jar";
      return reflectJar;
    }

    public Path getKotlinScriptRuntime() {
      Path reflectJar = getFolder().resolve("kotlin-script-runtime.jar");
      assert Files.exists(reflectJar) : "Expected kotlin script runtime jar";
      return reflectJar;
    }

    public Path getKotlinAnnotationJar() {
      Path annotationJar = getFolder().resolve("annotations-13.0.jar");
      assert Files.exists(annotationJar) : "Expected annotation jar";
      return annotationJar;
    }

    @Override
    public String toString() {
      return name;
    }
  }

  private final CfRuntime jdk;
  private final TestState state;
  private final KotlinCompiler compiler;
  private final KotlinTargetVersion targetVersion;
  private final List<Path> sources = new ArrayList<>();
  private final List<Path> classpath = new ArrayList<>();
  private final List<String> additionalArguments = new ArrayList<>();
  private boolean useJvmAssertions;
  // TODO(b/211590675): We should enable assertions by default.
  private boolean enableAssertions = true;
  private Path output = null;

  private KotlinCompilerTool(
      CfRuntime jdk, TestState state, KotlinCompiler compiler, KotlinTargetVersion targetVersion) {
    this.jdk = jdk;
    this.state = state;
    this.compiler = compiler;
    this.targetVersion = targetVersion;
  }

  public KotlinCompiler getCompiler() {
    return compiler;
  }

  public KotlinTargetVersion getTargetVersion() {
    return targetVersion;
  }

  public static KotlinCompilerTool create(
      CfRuntime jdk,
      TemporaryFolder temp,
      KotlinCompiler kotlinCompiler,
      KotlinTargetVersion kotlinTargetVersion) {
    return create(jdk, new TestState(temp), kotlinCompiler, kotlinTargetVersion);
  }

  public static KotlinCompilerTool create(
      CfRuntime jdk,
      TestState state,
      KotlinCompiler kotlinCompiler,
      KotlinTargetVersion kotlinTargetVersion) {
    return new KotlinCompilerTool(jdk, state, kotlinCompiler, kotlinTargetVersion);
  }

  public KotlinCompilerTool addArguments(String... arguments) {
    Collections.addAll(additionalArguments, arguments);
    return this;
  }

  public KotlinCompilerTool enableExperimentalContextReceivers() {
    return addArguments("-Xcontext-receivers");
  }

  public KotlinCompilerTool addSourceFiles(Path... files) {
    return addSourceFiles(Arrays.asList(files));
  }

  public KotlinCompilerTool addSourceFiles(Collection<Path> files) {
    sources.addAll(files);
    return this;
  }

  public KotlinCompilerTool addSourceFilesWithNonKtExtension(TemporaryFolder temp, Path... files) {
    return addSourceFilesWithNonKtExtension(temp, Arrays.asList(files));
  }

  public KotlinCompilerTool includeRuntime() {
    assert !additionalArguments.contains("-include-runtime");
    addArguments("-include-runtime");
    return this;
  }

  public KotlinCompilerTool noReflect() {
    assert !additionalArguments.contains("-no-reflect");
    addArguments("-no-reflect");
    return this;
  }

  public KotlinCompilerTool noStdLib() {
    assert !additionalArguments.contains("-no-stdlib");
    addArguments("-no-stdlib");
    return this;
  }

  public KotlinCompilerTool disableAssertions() {
    this.enableAssertions = false;
    return this;
  }

  public KotlinCompilerTool addSourceFilesWithNonKtExtension(
      TemporaryFolder temp, Collection<Path> files) {
    return addSourceFiles(
        files.stream()
            .map(
                fileNotNamedKt -> {
                  try {
                    // The Kotlin compiler does not require particular naming of files except for
                    // the extension, so just create a file called source.kt in a new directory.
                    String newFileName = getNameWithoutExtension(fileNotNamedKt.toString()) + ".kt";
                    Path fileNamedKt = temp.newFolder().toPath().resolve(newFileName);
                    Files.copy(fileNotNamedKt, fileNamedKt);
                    return fileNamedKt;
                  } catch (IOException e) {
                    throw new RuntimeException(e);
                  }
                })
            .collect(Collectors.toList()));
  }

  public KotlinCompilerTool addClasspathFiles(Path... files) {
    return addClasspathFiles(Arrays.asList(files));
  }

  public KotlinCompilerTool addClasspathFiles(Collection<Path> files) {
    classpath.addAll(files);
    return this;
  }

  public KotlinCompilerTool setOutputPath(Path file) {
    assertTrue("Output path must be an existing directory or a non-existing jar file",
        (!Files.exists(file) && FileUtils.isJarFile(file) && Files.exists(file.getParent()))
            || (Files.exists(file) && Files.isDirectory(file)));
    this.output = file;
    return this;
  }

  public KotlinCompilerTool setUseJvmAssertions(boolean useJvmAssertions) {
    this.useJvmAssertions = useJvmAssertions;
    return this;
  }

  public KotlinCompilerTool apply(Consumer<KotlinCompilerTool> consumer) {
    consumer.accept(this);
    return this;
  }

  private Path getOrCreateOutputPath() throws IOException {
    return output != null ? output : state.getNewTempFolder().resolve("out.jar");
  }

  /** Compile and return the compilations process result object. */
  public ProcessResult compileRaw() throws IOException {
    assertNotNull("An output path must be specified prior to compilation.", output);
    return compileInternal(output);
  }

  /** Compile asserting success and return the output path. */
  public Path compile() throws IOException {
    return compile(false);
  }

  public Path compile(boolean expectingFailure) throws IOException {
    Path output = getOrCreateOutputPath();
    ProcessResult result = compileInternal(output);
    if (expectingFailure) {
      assertNotEquals(result.toString(), result.exitCode, 0);
    } else {
      assertEquals(result.toString(), result.exitCode, 0);
    }
    return output;
  }

  private ProcessResult compileInternal(Path output) throws IOException {
    CommandLineAndHasherConsumers commandLineAndHasherConsumers =
        buildCommandLineAndHasherConsumers(output);
    CacheLookupKey cacheLookupKey = null;
    if (CommandResultCache.isEnabled()) {
      cacheLookupKey =
          new CacheLookupKey(
              hasher ->
                  commandLineAndHasherConsumers.hasherConsumers.forEach(
                      hasherConsumer -> hasherConsumer.acceptWithRuntimeException(hasher)));
      Pair<ProcessResult, Path> lookupResult =
          CommandResultCache.getInstance().lookup(cacheLookupKey);
      if (lookupResult != null
          && lookupResult.getFirst().exitCode == 0
          && lookupResult.getSecond() != null) {
        Files.copy(lookupResult.getSecond(), output);
        return lookupResult.getFirst();
      }
    }
    ProcessBuilder builder = new ProcessBuilder(commandLineAndHasherConsumers.cmdline);
    builder.directory(new File(ToolHelper.getProjectRoot()));
    ProcessResult processResult = ToolHelper.runProcess(builder);
    if (CommandResultCache.isEnabled() && output.toFile().isFile()) {
      CommandResultCache.getInstance().putResult(processResult, cacheLookupKey, output);
    }
    return processResult;
  }

  public static class CommandLineAndHasherConsumers {
    final List<String> cmdline = new ArrayList<>();
    final List<ThrowingConsumer<Hasher, IOException>> hasherConsumers = new ArrayList<>();
  }

  private CommandLineAndHasherConsumers buildCommandLineAndHasherConsumers(Path output)
      throws IOException {
    CommandLineAndHasherConsumers commandLineAndHasherConsumers =
        new CommandLineAndHasherConsumers();
    List<String> cmdline = commandLineAndHasherConsumers.cmdline;
    cmdline.add(jdk.getJavaExecutable().toString());
    if (enableAssertions) {
      cmdline.add("-ea");
    }
    cmdline.add("-cp");
    cmdline.add(compiler.getCompiler().toString());
    cmdline.add(ToolHelper.K2JVMCompiler);
    if (useJvmAssertions) {
      cmdline.add("-Xassertions=jvm");
    }
    cmdline.add("-jdk-home");
    cmdline.add(jdk.getJavaHome().toString());
    cmdline.add("-jvm-target");
    cmdline.add(targetVersion.getJvmTargetString());
    // Until now this is just command line files, no inputs, hash existing command
    String noneFileCommandLineArguments = StringUtils.join("", cmdline);
    commandLineAndHasherConsumers.hasherConsumers.add(
        hasher -> hasher.putString(noneFileCommandLineArguments, StandardCharsets.UTF_8));

    for (Path source : sources) {
      cmdline.add(source.toString());
      commandLineAndHasherConsumers.hasherConsumers.add(
          hasher -> hasher.putBytes(Files.readAllBytes(source)));
    }
    cmdline.add("-d");
    cmdline.add(output.toString());
    if (!classpath.isEmpty()) {
      cmdline.add("-cp");
      cmdline.add(classpath
          .stream()
          .map(Path::toString)
          .collect(Collectors.joining(isWindows() ? ";" : ":")));
      for (Path path : classpath) {
        commandLineAndHasherConsumers.hasherConsumers.add(
            hasher -> {
              hasher.putString("--cp", StandardCharsets.UTF_8);
              hasher.putBytes(Files.readAllBytes(path));
            });
      }
    }
    cmdline.addAll(additionalArguments);
    commandLineAndHasherConsumers.hasherConsumers.add(
        hasher -> additionalArguments.forEach(s -> hasher.putString(s, StandardCharsets.UTF_8)));
    return commandLineAndHasherConsumers;
  }


}
