// 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.debug.DebugTestConfig;
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)
      throws CompilationFailedException {
    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) {
        command.add("-dontshrink");
      }
      if (!enableOptimization) {
        command.add("-dontoptimize");
      }
      if (!enableMinification) {
        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(getState(), outJar, minApiLevel, 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 DebugTestConfig debugConfig() {
    throw new Unimplemented("No support for debug config");
  }

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