// 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.apiusagesample;

import com.android.tools.r8.ArchiveClassFileProvider;
import com.android.tools.r8.ArchiveProgramResourceProvider;
import com.android.tools.r8.AssertionsConfiguration;
import com.android.tools.r8.CompilationFailedException;
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.DexIndexedConsumer;
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.ProgramResource;
import com.android.tools.r8.ProgramResource.Kind;
import com.android.tools.r8.ProgramResourceProvider;
import com.android.tools.r8.R8;
import com.android.tools.r8.R8Command;
import com.android.tools.r8.ResourceException;
import com.android.tools.r8.StringConsumer;
import com.android.tools.r8.Version;
import com.android.tools.r8.origin.ArchiveEntryOrigin;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.StringUtils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
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.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class R8ApiUsageSample {

  private static final Origin origin =
      new Origin(Origin.root()) {
        @Override
        public String part() {
          return "R8ApiUsageSample";
        }
      };

  private static final DiagnosticsHandler handler = new D8DiagnosticsHandler();

  /**
   * Example invocation:
   *
   * <pre>
   *   java -jar r8-api-uses.jar \
   *     --output path/to/output/dir \
   *     --min-api minApiLevel \
   *     --lib path/to/library.jar \
   *     path/to/input{1,2,3}.{jar,class}
   * </pre>
   */
  public static void main(String[] args) {
    // Check version API
    checkVersionApi();
    // Parse arguments with the commandline parser to make use of its API.
    R8Command.Builder cmd = R8Command.parse(args, origin);
    CompilationMode mode = cmd.getMode();
    Path temp = cmd.getOutputPath();
    int minApiLevel = cmd.getMinApiLevel();
    // The Builder API does not provide access to the concrete paths
    // (everything is put into providers) so manually parse them here.
    List<Path> libraries = new ArrayList<>(1);
    List<Path> mainDexList = new ArrayList<>(1);
    List<Path> mainDexRules = new ArrayList<>(1);
    List<Path> pgConf = new ArrayList<>(1);
    List<Path> inputs = new ArrayList<>(args.length);
    for (int i = 0; i < args.length; i++) {
      if (args[i].equals("--lib")) {
        libraries.add(Paths.get(args[++i]));
      } else if (args[i].equals("--main-dex-list")) {
        mainDexList.add(Paths.get(args[++i]));
      } else if (args[i].equals("--main-dex-rules")) {
        mainDexRules.add(Paths.get(args[++i]));
      } else if (args[i].equals("--pg-conf")) {
        pgConf.add(Paths.get(args[++i]));
      } else if (isArchive(args[i]) || isClassFile(args[i])) {
        inputs.add(Paths.get(args[i]));
      }
    }
    if (!Files.exists(temp) || !Files.isDirectory(temp)) {
      throw new RuntimeException("Must supply a temp/output directory");
    }
    if (inputs.isEmpty()) {
      throw new RuntimeException("Must supply program inputs");
    }
    if (libraries.isEmpty()) {
      throw new RuntimeException("Must supply library inputs");
    }
    if (mainDexList.isEmpty()) {
      throw new RuntimeException("Must supply main-dex-list inputs");
    }
    if (mainDexRules.isEmpty()) {
      throw new RuntimeException("Must supply main-dex-rules inputs");
    }
    if (pgConf.isEmpty()) {
      throw new RuntimeException("Must supply pg-conf inputs");
    }

    useProgramFileList(CompilationMode.DEBUG, minApiLevel, libraries, inputs);
    useProgramFileList(CompilationMode.RELEASE, minApiLevel, libraries, inputs);
    useProgramData(minApiLevel, libraries, inputs);
    useProgramResourceProvider(minApiLevel, libraries, inputs);
    useLibraryResourceProvider(minApiLevel, libraries, inputs);
    useMainDexListFiles(minApiLevel, libraries, inputs, mainDexList);
    useMainDexClasses(minApiLevel, libraries, inputs, mainDexList);
    useMainDexRulesFiles(minApiLevel, libraries, inputs, mainDexRules);
    useMainDexRules(minApiLevel, libraries, inputs, mainDexRules);
    useProguardConfigFiles(minApiLevel, libraries, inputs, mainDexList, pgConf);
    useProguardConfigLines(minApiLevel, libraries, inputs, mainDexList, pgConf);
    useAssertionConfig(minApiLevel, libraries, inputs);
    useVArgVariants(minApiLevel, libraries, inputs, mainDexList, mainDexRules, pgConf);
    useProguardConfigConsumers(minApiLevel, libraries, inputs, pgConf);
  }

  private static class InMemoryStringConsumer implements StringConsumer {
    public String value = null;

    @Override
    public void accept(String string, DiagnosticsHandler handler) {
      value = string;
    }
  }

  private static void useProguardConfigConsumers(
      int minApiLevel, Collection<Path> libraries, Collection<Path> inputs, List<Path> pgConf) {
    InMemoryStringConsumer usageConsumer = new InMemoryStringConsumer();
    InMemoryStringConsumer seedsConsumer = new InMemoryStringConsumer();
    InMemoryStringConsumer configConsumer = new InMemoryStringConsumer();
    try {
      R8.run(
          R8Command.builder(handler)
              .setMinApiLevel(minApiLevel)
              .setProgramConsumer(new EnsureOutputConsumer())
              .addLibraryFiles(libraries)
              .addProgramFiles(inputs)
              .addProguardConfigurationFiles(pgConf)
              .setProguardUsageConsumer(usageConsumer)
              .setProguardSeedsConsumer(seedsConsumer)
              .setProguardConfigurationConsumer(configConsumer)
              .build());
    } catch (CompilationFailedException e) {
      throw new RuntimeException("Unexpected compilation exception", e);
    }
    if (usageConsumer.value == null) {
      throw new RuntimeException("Expected usage info but had none");
    }
    if (seedsConsumer.value == null) {
      throw new RuntimeException("Expected seeds info but had none");
    }
    if (configConsumer.value == null) {
      throw new RuntimeException("Expected config info but had none");
    }
  }

  // Check API support for compiling Java class-files from the file system.
  private static void useProgramFileList(
      CompilationMode mode, int minApiLevel, Collection<Path> libraries, Collection<Path> inputs) {
    try {
      R8.run(
          R8Command.builder(handler)
              .setMode(mode)
              .setMinApiLevel(minApiLevel)
              .setDisableTreeShaking(true)
              .setDisableMinification(true)
              .setProgramConsumer(new EnsureOutputConsumer())
              .addLibraryFiles(libraries)
              .addProgramFiles(inputs)
              .build());
    } catch (CompilationFailedException e) {
      throw new RuntimeException("Unexpected compilation exceptions", e);
    }
  }

  // Check API support for compiling Java class-files from byte content.
  private static void useProgramData(
      int minApiLevel, Collection<Path> libraries, Collection<Path> inputs) {
    try {
      R8Command.Builder builder =
          R8Command.builder(handler)
              .setMinApiLevel(minApiLevel)
              .setDisableTreeShaking(true)
              .setDisableMinification(true)
              .setProgramConsumer(new EnsureOutputConsumer())
              .addLibraryFiles(libraries);
      for (ClassFileContent classfile : readClassFiles(inputs)) {
        builder.addClassProgramData(classfile.data, classfile.origin);
      }
      R8.run(builder.build());
    } catch (CompilationFailedException e) {
      throw new RuntimeException("Unexpected compilation exceptions", e);
    } catch (IOException e) {
      throw new RuntimeException("Unexpected IO exception", e);
    }
  }

  // Check API support for compiling Java class-files from a program provider abstraction.
  private static void useProgramResourceProvider(
      int minApiLevel, Collection<Path> libraries, Collection<Path> inputs) {
    try {
      R8Command.Builder builder =
          R8Command.builder(handler)
              .setMinApiLevel(minApiLevel)
              .setDisableTreeShaking(true)
              .setDisableMinification(true)
              .setProgramConsumer(new EnsureOutputConsumer())
              .addLibraryFiles(libraries);
      for (Path input : inputs) {
        if (isArchive(input)) {
          builder.addProgramResourceProvider(
              ArchiveProgramResourceProvider.fromArchive(
                  input, ArchiveProgramResourceProvider::includeClassFileEntries));
        } else {
          builder.addProgramResourceProvider(
              new ProgramResourceProvider() {
                @Override
                public Collection<ProgramResource> getProgramResources() throws ResourceException {
                  return Collections.singleton(ProgramResource.fromFile(Kind.CF, input));
                }
              });
        }
      }
      R8.run(builder.build());
    } catch (CompilationFailedException e) {
      throw new RuntimeException("Unexpected compilation exceptions", e);
    }
  }

  private static void useLibraryResourceProvider(
      int minApiLevel, Collection<Path> libraries, Collection<Path> inputs) {
    try {
      R8Command.Builder builder =
          R8Command.builder(handler)
              .setMinApiLevel(minApiLevel)
              .setDisableTreeShaking(true)
              .setDisableMinification(true)
              .setProgramConsumer(new EnsureOutputConsumer())
              .addProgramFiles(inputs);
      for (Path library : libraries) {
        builder.addLibraryResourceProvider(new ArchiveClassFileProvider(library));
      }
      R8.run(builder.build());
    } catch (CompilationFailedException e) {
      throw new RuntimeException("Unexpected compilation exceptions", e);
    } catch (IOException e) {
      throw new RuntimeException("Unexpected IO exception", e);
    }
  }

  private static void useMainDexListFiles(
      int minApiLevel,
      Collection<Path> libraries,
      Collection<Path> inputs,
      Collection<Path> mainDexList) {
    try {
      R8.run(
          R8Command.builder(handler)
              .setMinApiLevel(minApiLevel)
              .setDisableTreeShaking(true)
              .setDisableMinification(true)
              .setProgramConsumer(new EnsureOutputConsumer())
              .addLibraryFiles(libraries)
              .addProgramFiles(inputs)
              .addMainDexListFiles(mainDexList)
              .build());
    } catch (CompilationFailedException e) {
      throw new RuntimeException("Unexpected compilation exceptions", e);
    }
  }

  private static void useMainDexClasses(
      int minApiLevel,
      Collection<Path> libraries,
      Collection<Path> inputs,
      Collection<Path> mainDexList) {
    try {
      List<String> mainDexClasses = new ArrayList<>(1);
      for (Path path : mainDexList) {
        for (String line : Files.readAllLines(path)) {
          String entry = line.trim();
          if (entry.isEmpty() || entry.startsWith("#") || !entry.endsWith(".class")) {
            continue;
          }
          mainDexClasses.add(entry.replace(".class", "").replace("/", "."));
        }
      }
      R8.run(
          R8Command.builder(handler)
              .setMinApiLevel(minApiLevel)
              .setDisableTreeShaking(true)
              .setDisableMinification(true)
              .setProgramConsumer(new EnsureOutputConsumer())
              .addLibraryFiles(libraries)
              .addProgramFiles(inputs)
              .addMainDexClasses(mainDexClasses)
              .build());
    } catch (CompilationFailedException e) {
      throw new RuntimeException("Unexpected compilation exceptions", e);
    } catch (IOException e) {
      throw new RuntimeException("Unexpected IO exception", e);
    }
  }

  private static void useMainDexRulesFiles(
      int minApiLevel,
      Collection<Path> libraries,
      Collection<Path> inputs,
      Collection<Path> mainDexRules) {
    try {
      R8.run(
          R8Command.builder(handler)
              .setMinApiLevel(minApiLevel)
              .setDisableTreeShaking(true)
              .setDisableMinification(true)
              .setProgramConsumer(new EnsureOutputConsumer())
              .addLibraryFiles(libraries)
              .addProgramFiles(inputs)
              .addMainDexRulesFiles(mainDexRules)
              .build());
    } catch (CompilationFailedException e) {
      throw new RuntimeException("Unexpected compilation exceptions", e);
    }
  }

  private static void useMainDexRules(
      int minApiLevel,
      Collection<Path> libraries,
      Collection<Path> inputs,
      Collection<Path> mainDexRulesFiles) {
    try {
      R8Command.Builder builder =
          R8Command.builder(handler)
              .setMinApiLevel(minApiLevel)
              .setDisableTreeShaking(true)
              .setDisableMinification(true)
              .setProgramConsumer(new EnsureOutputConsumer())
              .addLibraryFiles(libraries)
              .addProgramFiles(inputs);
      for (Path mainDexRulesFile : mainDexRulesFiles) {
        builder.addMainDexRules(
            Files.readAllLines(mainDexRulesFile), new PathOrigin(mainDexRulesFile));
      }
      R8.run(builder.build());
    } catch (CompilationFailedException e) {
      throw new RuntimeException("Unexpected compilation exceptions", e);
    } catch (IOException e) {
      throw new RuntimeException("Unexpected IO exception", e);
    }
  }

  private static void useProguardConfigFiles(
      int minApiLevel,
      Collection<Path> libraries,
      Collection<Path> inputs,
      Collection<Path> mainDexList,
      List<Path> pgConf) {
    try {
      R8.run(
          R8Command.builder(handler)
              .setMinApiLevel(minApiLevel)
              .setProgramConsumer(new EnsureOutputConsumer())
              .addLibraryFiles(libraries)
              .addProgramFiles(inputs)
              .addMainDexListFiles(mainDexList)
              .addProguardConfigurationFiles(pgConf)
              .build());
    } catch (CompilationFailedException e) {
      throw new RuntimeException("Unexpected compilation exceptions", e);
    }
  }

  private static void useProguardConfigLines(
      int minApiLevel,
      Collection<Path> libraries,
      Collection<Path> inputs,
      Collection<Path> mainDexList,
      List<Path> pgConf) {
    try {
      R8Command.Builder builder =
          R8Command.builder(handler)
              .setMinApiLevel(minApiLevel)
              .setProgramConsumer(new EnsureOutputConsumer())
              .addLibraryFiles(libraries)
              .addProgramFiles(inputs)
              .addMainDexListFiles(mainDexList);
      for (Path file : pgConf) {
        builder.addProguardConfiguration(Files.readAllLines(file), new PathOrigin(file));
      }
      R8.run(builder.build());
    } catch (CompilationFailedException e) {
      throw new RuntimeException("Unexpected compilation exceptions", e);
    } catch (IOException e) {
      throw new RuntimeException("Unexpected IO exception", e);
    }
  }

  private static void useAssertionConfig(
      int minApiLevel, Collection<Path> libraries, Collection<Path> inputs) {
    try {
      R8.run(
          R8Command.builder(handler)
              .setDisableTreeShaking(true)
              .setMinApiLevel(minApiLevel)
              .setProgramConsumer(new EnsureOutputConsumer())
              .addLibraryFiles(libraries)
              .addProgramFiles(inputs)
              .addAssertionsConfiguration(b -> b.setScopeAll().setCompileTimeEnable().build())
              .addAssertionsConfiguration(b -> b.setScopeAll().setCompileTimeDisable().build())
              .addAssertionsConfiguration(
                  b ->
                      b.setScopePackage("com.android.tools.apiusagesample")
                          .setCompileTimeEnable()
                          .build())
              .addAssertionsConfiguration(
                  b ->
                      b.setScopePackage("com.android.tools.apiusagesample")
                          .setPassthrough()
                          .build())
              .addAssertionsConfiguration(
                  b ->
                      b.setScopePackage("com.android.tools.apiusagesample")
                          .setCompileTimeDisable()
                          .build())
              .addAssertionsConfiguration(
                  b ->
                      b.setScopeClass("com.android.tools.apiusagesample.D8ApiUsageSample")
                          .setCompileTimeEnable()
                          .build())
              .addAssertionsConfiguration(
                  b ->
                      b.setScopeClass("com.android.tools.apiusagesample.D8ApiUsageSample")
                          .setPassthrough()
                          .build())
              .addAssertionsConfiguration(
                  b ->
                      b.setScopeClass("com.android.tools.apiusagesample.D8ApiUsageSample")
                          .setCompileTimeDisable()
                          .build())
              .addAssertionsConfiguration(
                  AssertionsConfiguration.Builder::compileTimeEnableAllAssertions)
              .addAssertionsConfiguration(AssertionsConfiguration.Builder::passthroughAllAssertions)
              .addAssertionsConfiguration(
                  AssertionsConfiguration.Builder::compileTimeDisableAllAssertions)
              .build());
    } catch (CompilationFailedException e) {
      throw new RuntimeException("Unexpected compilation exceptions", e);
    }
  }

  // Check API support for all the varg variants.
  private static void useVArgVariants(
      int minApiLevel,
      List<Path> libraries,
      List<Path> inputs,
      List<Path> mainDexList,
      List<Path> mainDexRules,
      List<Path> pgConf) {
    try {
      R8.run(
          R8Command.builder(handler)
              .setMinApiLevel(minApiLevel)
              .setProgramConsumer(new EnsureOutputConsumer())
              .addLibraryFiles(libraries.get(0))
              .addLibraryFiles(libraries.stream().skip(1).toArray(Path[]::new))
              .addProgramFiles(inputs.get(0))
              .addProgramFiles(inputs.stream().skip(1).toArray(Path[]::new))
              .addMainDexListFiles(mainDexList.get(0))
              .addMainDexListFiles(mainDexList.stream().skip(1).toArray(Path[]::new))
              .addMainDexRulesFiles(mainDexRules.get(0))
              .addMainDexRulesFiles(mainDexRules.stream().skip(1).toArray(Path[]::new))
              .addProguardConfigurationFiles(pgConf.get(0))
              .addProguardConfigurationFiles(pgConf.stream().skip(1).toArray(Path[]::new))
              .build());
    } catch (CompilationFailedException e) {
      throw new RuntimeException("Unexpected compilation exceptions", e);
    }
  }

  // Helpers for tests.
  // Some of this reimplements stuff in R8 utils, but that is not public API and we should not
  // rely on it.

  private static List<ClassFileContent> readClassFiles(Collection<Path> files) throws IOException {
    List<ClassFileContent> classfiles = new ArrayList<>();
    for (Path file : files) {
      if (isArchive(file)) {
        Origin zipOrigin = new PathOrigin(file);
        ZipInputStream zip = new ZipInputStream(Files.newInputStream(file), StandardCharsets.UTF_8);
        ZipEntry entry;
        while (null != (entry = zip.getNextEntry())) {
          String name = entry.getName();
          if (isClassFile(name)) {
            Origin origin = new ArchiveEntryOrigin(name, zipOrigin);
            classfiles.add(new ClassFileContent(origin, readBytes(zip)));
          }
        }
      } else if (isClassFile(file)) {
        classfiles.add(new ClassFileContent(new PathOrigin(file), Files.readAllBytes(file)));
      }
    }
    return classfiles;
  }

  private static byte[] readBytes(InputStream stream) throws IOException {
    try (ByteArrayOutputStream bytes = new ByteArrayOutputStream()) {
      byte[] buffer = new byte[0xffff];
      for (int length; (length = stream.read(buffer)) != -1; ) {
        bytes.write(buffer, 0, length);
      }
      return bytes.toByteArray();
    }
  }

  private static boolean isClassFile(Path file) {
    return isClassFile(file.toString());
  }

  private static boolean isClassFile(String file) {
    file = StringUtils.toLowerCase(file);
    return file.endsWith(".class");
  }

  private static boolean isArchive(Path file) {
    return isArchive(file.toString());
  }

  private static boolean isArchive(String file) {
    file = StringUtils.toLowerCase(file);
    return file.endsWith(".zip") || file.endsWith(".jar");
  }

  private static class ClassFileContent {
    final Origin origin;
    final byte[] data;

    public ClassFileContent(Origin origin, byte[] data) {
      this.origin = origin;
      this.data = data;
    }
  }

  private static class EnsureOutputConsumer implements DexIndexedConsumer {
    boolean hasOutput = false;

    @Override
    public synchronized void accept(
        int fileIndex, byte[] data, Set<String> descriptors, DiagnosticsHandler handler) {
      hasOutput = true;
    }

    @Override
    public void finished(DiagnosticsHandler handler) {
      if (!hasOutput) {
        handler.error(new StringDiagnostic("Expected to produce output but had none"));
      }
    }
  }

  private static void checkVersionApi() {
    String labelValue;
    int labelAccess;
    try {
      Field field = Version.class.getDeclaredField("LABEL");
      labelAccess = field.getModifiers();
      labelValue = (String) field.get(Version.class);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
    if (!Modifier.isPublic(labelAccess)
        || !Modifier.isStatic(labelAccess)
        || !Modifier.isFinal(labelAccess)) {
      throw new RuntimeException("Expected public static final LABEL");
    }
    if (labelValue.isEmpty()) {
      throw new RuntimeException("Expected LABEL constant");
    }
    if (Version.LABEL.isEmpty()) {
      throw new RuntimeException("Expected LABEL constant");
    }
    if (Version.getVersionString() == null) {
      throw new RuntimeException("Expected getVersionString API");
    }
    if (Version.getMajorVersion() < -1) {
      throw new RuntimeException("Expected getMajorVersion API");
    }
    if (Version.getMinorVersion() < -1) {
      throw new RuntimeException("Expected getMinorVersion API");
    }
    if (Version.getPatchVersion() < -1) {
      throw new RuntimeException("Expected getPatchVersion API");
    }
    if (Version.getPreReleaseString() == null && false) {
      throw new RuntimeException("Expected getPreReleaseString API");
    }
    if (Version.isDevelopmentVersion() && false) {
      throw new RuntimeException("Expected isDevelopmentVersion API");
    }
  }
}
