// 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.ToolHelper.isWindows;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import com.android.tools.r8.TestRuntime.CfRuntime;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.ZipUtils;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.rules.TemporaryFolder;

public class JavaCompilerTool {

  private final CfRuntime jdk;
  private final TestState state;
  private String source = null;
  private String target = null;
  private final List<Path> sources = new ArrayList<>();
  private final List<String> classNames = new ArrayList<>();
  private final List<Path> classpath = new ArrayList<>();
  private final List<String> options = new ArrayList<>();
  private final List<Path> annotationProcessorPath = new ArrayList<>();
  private final List<String> annotationProcessors = new ArrayList<>();
  private Path output = null;

  private JavaCompilerTool(CfRuntime jdk, TestState state) {
    this.jdk = jdk;
    this.state = state;
  }

  public static JavaCompilerTool create(CfRuntime jdk, TemporaryFolder temp) {
    assert temp != null;
    return create(jdk, new TestState(temp));
  }

  public static JavaCompilerTool create(CfRuntime jdk, TestState state) {
    assert state != null;
    return new JavaCompilerTool(jdk, state);
  }

  public JavaCompilerTool addOptions(String... options) {
    return addOptions(Arrays.asList(options));
  }

  public JavaCompilerTool addOptions(Collection<String> options) {
    this.options.addAll(options);
    return this;
  }

  public JavaCompilerTool setSource(String source) {
    this.source = source;
    return this;
  }

  public JavaCompilerTool setTarget(String target) {
    this.target = target;
    return this;
  }

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

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

  public JavaCompilerTool addClassNames(Collection<String> classNames) {
    this.classNames.addAll(classNames);
    return this;
  }

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

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

  public JavaCompilerTool addAnnotationProcessorPathFiles(Path... files) {
    return addAnnotationProcessorPathFiles(Arrays.asList(files));
  }

  public JavaCompilerTool addAnnotationProcessorPathFiles(Collection<Path> files) {
    annotationProcessorPath.addAll(files);
    return this;
  }

  public JavaCompilerTool addAnnotationProcessors(String... processors) {
    return addAnnotationProcessor(Arrays.asList(processors));
  }

  public JavaCompilerTool addAnnotationProcessor(Collection<String> processors) {
    annotationProcessors.addAll(processors);
    return this;
  }

  /** Set the output. Must be to an existing directory or to an non-existing jar file. */
  public JavaCompilerTool setOutputPath(Path file) {
    assert (Files.exists(file) && Files.isDirectory(file))
        || (!Files.exists(file) && FileUtils.isJarFile(file) && Files.exists(file.getParent()));
    this.output = file;
    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 path to the output file.
   *
   * <p>If no output file has been set, the output is compiled to a zip archive in a temporary
   * directory.
   */
  public Path compile() throws IOException {
    Path output = getOrCreateOutputPath();
    ProcessResult result = compileInternal(output);
    assertEquals(result.toString(), result.exitCode, 0);
    return output;
  }

  // For javac command line options see
  // https://docs.oracle.com/en/java/javase/17/docs/specs/man/javac.html.
  private ProcessResult compileInternal(Path output) throws IOException {
    Path outdir = Files.isDirectory(output) ? output : state.getNewTempFolder();
    List<String> cmdline = new ArrayList<>();
    cmdline.add(jdk.getJavaExecutable() + "c");
    cmdline.addAll(options);
    if (!classpath.isEmpty()) {
      cmdline.add("-cp");
      cmdline.add(
          classpath.stream()
              .map(Path::toString)
              .collect(Collectors.joining(isWindows() ? ";" : ":")));
    }
    if (!annotationProcessorPath.isEmpty()) {
      cmdline.add("-processorpath");
      cmdline.add(
          annotationProcessorPath.stream()
              .map(Path::toString)
              .collect(Collectors.joining(isWindows() ? ";" : ":")));
    }
    if (!annotationProcessors.isEmpty()) {
      cmdline.add("-processor");
      cmdline.add(String.join(",", annotationProcessors));
    }
    if (source != null) {
      cmdline.add("-source");
      cmdline.add(source);
    }
    if (target != null) {
      cmdline.add("-target");
      cmdline.add(target);
    }
    cmdline.add("-d");
    cmdline.add(outdir.toString());
    for (Path source : sources) {
      cmdline.add(source.toString());
    }
    cmdline.addAll(classNames);
    ProcessBuilder builder = new ProcessBuilder(cmdline);
    ProcessResult javacResult = ToolHelper.runProcess(builder);
    if (FileUtils.isJarFile(output)) {
      assert !outdir.equals(output);
      ZipUtils.zip(output, outdir);
    }
    return javacResult;
  }
}
