// Copyright (c) 2018, 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 com.android.tools.r8.R8Command.Builder;
import com.android.tools.r8.TestBase.Backend;
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.benchmarks.BenchmarkResults;
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.FileUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.base.Charsets;
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.function.Consumer;
import java.util.function.Supplier;

// The type arguments R8Command, Builder is not relevant for running Proguard.
public class ProguardTestBuilder
    extends TestShrinkerBuilder<
        R8Command, Builder, ProguardTestCompileResult, ProguardTestRunResult, ProguardTestBuilder> {

  // Version of Proguard to use.
  private final ProguardVersion version;

  // Ordered list of injar entries.
  private List<Path> injars = new ArrayList<>();

  // Ordered list of libraryjar entries.
  private List<Path> libraryjars = new ArrayList<>();

  // Proguard configuration file lines.
  private List<String> config = new ArrayList<>();

  // Additional Proguard configuration files.
  private List<Path> proguardConfigFiles = new ArrayList<>();

  private ProguardTestBuilder(
      TestState state, ProguardVersion version, Builder builder, Backend backend) {
    super(state, builder, backend);
    this.version = version;
  }

  public static ProguardTestBuilder create(TestState state, ProguardVersion version) {
    return new ProguardTestBuilder(state, version, R8Command.builder(), Backend.CF);
  }

  @Override
  public boolean isProguardTestBuilder() {
    return true;
  }

  @Override
  ProguardTestBuilder self() {
    return this;
  }

  @Override
  ProguardTestCompileResult internalCompile(
      Builder builder,
      Consumer<InternalOptions> optionsConsumer,
      Supplier<AndroidApp> app,
      BenchmarkResults benchmarkResults)
      throws CompilationFailedException {
    assert benchmarkResults == null;
    assert !libraryDesugaringTestConfiguration.isEnabled();
    try {
      Path proguardOutputFolder = getState().getNewTempFolder();
      Path outJar = proguardOutputFolder.resolve("output.jar");
      Path configFile = proguardOutputFolder.resolve("configuration.txt");
      Path mapFile = proguardOutputFolder.resolve("mapping.txt");
      FileUtils.writeTextFile(configFile, config);
      List<String> command = new ArrayList<>();
      command.add(version.getProguardScript().toString());
      // Without -forceprocessing Proguard just checks the creation time on the in/out jars.
      command.add("-forceprocessing");
      for (Path injar : injars) {
        command.add("-injars");
        command.add(injar.toString());
      }
      for (Path libraryjar : libraryjars) {
        command.add("-libraryjars");
        command.add(libraryjar.toString());
      }
      if (libraryjars.isEmpty()) {
        command.add("-libraryjars");
        // TODO(sgjesse): Add support for running with Android Jar.
        // command.add(ToolHelper.getAndroidJar(AndroidApiLevel.P).toString());
        command.add(ToolHelper.getJava8RuntimeJar().toString());
      }
      command.add("-include");
      command.add(configFile.toString());
      for (Path proguardConfigFile : proguardConfigFiles) {
        command.add("-include");
        command.add(proguardConfigFile.toAbsolutePath().toString());
      }
      command.add("-outjar");
      command.add(outJar.toString());
      command.add("-printmapping");
      command.add(mapFile.toString());
      if (enableTreeShaking.isFalse()) {
        command.add("-dontshrink");
      }
      if (enableMinification.isFalse()) {
        command.add("-dontobfuscate");
      }
      ProcessBuilder pbuilder = new ProcessBuilder(command);
      ProcessResult result = ToolHelper.runProcess(pbuilder, getStdoutForTesting());
      if (result.exitCode != 0) {
        throw new CompilationFailedException(result.toString());
      }
      String proguardMap =
          Files.exists(mapFile) ? FileUtils.readTextFile(mapFile, Charsets.UTF_8) : "";
      return new ProguardTestCompileResult(
          result, getState(), outJar, getMinApiLevel(), proguardMap);
    } catch (IOException e) {
      throw new CompilationFailedException(e);
    }
  }

  @Override
  public ProguardTestBuilder addApplyMapping(String proguardMap) {
    throw new Unimplemented("No support for adding mapfile content yet");
  }

  @Override
  public ProguardTestBuilder addDataEntryResources(DataEntryResource... resources) {
    throw new Unimplemented("No support for adding data entry resources");
  }

  @Override
  public ProguardTestBuilder addProgramClasses(Collection<Class<?>> classes) {
    // Adding a collection of classes will build a jar of exactly those classes so that no other
    // classes are made available via a too broad classpath directory.
    try {
      Path out = getState().getNewTempFolder().resolve("out.jar");
      TestBase.writeClassesToJar(out, classes);
      injars.add(out);
      return self();
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  @Override
  public ProguardTestBuilder addProgramFiles(Collection<Path> files) {
    List<Path> classfiles = new ArrayList<>(files.size());
    for (Path file : files) {
      if (FileUtils.isJarFile(file)) {
        injars.add(file);
      } else if (FileUtils.isClassFile(file)) {
        classfiles.add(file);
      } else {
        throw new Unimplemented("No support for adding non-jar or non classfiles.");
      }
    }
    if (!classfiles.isEmpty()) {
      try {
        Path out = getState().getNewTempFolder().resolve("out.jar");
        TestBase.writeClassFilesToJar(out, classfiles);
        injars.add(out);
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    }
    return self();
  }

  @Override
  public ProguardTestBuilder addProgramClassFileData(Collection<byte[]> classes) {
    try {
      Path out = getState().getNewTempFolder().resolve("out.jar");
      TestBase.writeClassFileDataToJar(out, classes);
      injars.add(out);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
    return self();
  }

  @Override
  public ProguardTestBuilder addProgramDexFileData(Collection<byte[]> data) {
    throw new Unimplemented("No support for adding dex file data directly");
  }

  @Override
  public ProguardTestBuilder addKeepRuleFiles(List<Path> proguardConfigFiles) {
    this.proguardConfigFiles.addAll(proguardConfigFiles);
    return self();
  }

  @Override
  public ProguardTestBuilder addKeepRules(Collection<String> rules) {
    config.addAll(rules);
    return self();
  }
  @Override
  public ProguardTestBuilder addLibraryFiles(Collection<Path> files) {
    for (Path file : files) {
      if (FileUtils.isJarFile(file)) {
        libraryjars.add(file);
      } else {
        throw new Unimplemented(
            "No support for adding class files directly (we need to compute the descriptor)");
      }
    }
    return self();
  }

  @Override
  public ProguardTestBuilder addLibraryClasses(Class<?>... classes) {
    addLibraryClasses(Arrays.asList(classes));
    return self();
  }

  @Override
  public ProguardTestBuilder addLibraryClasses(Collection<Class<?>> classes) {
    List<Path> pathsForClasses = new ArrayList<>(classes.size());
    for (Class<?> clazz : classes) {
      pathsForClasses.add(ToolHelper.getClassFileForTestClass(clazz));
    }
    try {
      Path out = getState().getNewTempFolder().resolve("out.jar");
      TestBase.writeClassFilesToJar(out, pathsForClasses);
      libraryjars.add(out);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
    return self();
  }

  @Override
  public ProguardTestBuilder addClasspathClasses(Collection<Class<?>> classes) {
    throw new Unimplemented("No support for adding classpath data directly");
  }

  @Override
  public ProguardTestBuilder addClasspathFiles(Collection<Path> files) {
    throw new Unimplemented("No support for adding classpath data directly");
  }

  @Override
  public ProguardTestBuilder setProgramConsumer(ProgramConsumer programConsumer) {
    throw new Unimplemented("No support for program consumer");
  }

  @Override
  public ProguardTestBuilder setMinApi(int minApiLevel) {
    if (backend == Backend.DEX) {
      throw new Unimplemented("No support for setting min api");
    }
    return self();
  }

  @Override
  public ProguardTestBuilder addMainDexListFiles(Collection<Path> files) {
    throw new Unimplemented("No support for adding main dex list files");
  }

  @Override
  public ProguardTestBuilder setMainDexListConsumer(StringConsumer consumer) {
    throw new Unimplemented("No support for main dex list consumer");
  }

  @Override
  public ProguardTestBuilder setMode(CompilationMode mode) {
    throw new Unimplemented("No support for setting compilation mode");
  }

  @Override
  public ProguardTestBuilder disableDesugaring() {
    throw new Unimplemented("No support for disabling desugaring");
  }

  @Override
  public ProguardTestBuilder addOptionsModification(Consumer<InternalOptions> optionsConsumer) {
    throw new Unimplemented("No support for changing internal options");
  }
}
