// Copyright (c) 2017, 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.CompilationException;
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.D8;
import com.android.tools.r8.D8Command;
import com.android.tools.r8.utils.OutputMode;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class D8Compiler {
  private int minSdkVersion;
  private Path bootclasspath;
  private List<Path> classpath;
  private static ExecutorService pool = Executors.newFixedThreadPool(4);

  private D8Compiler(int minSdkVersion, Path bootclasspath, List<Path> classpath) {
    this.minSdkVersion = minSdkVersion;
    this.bootclasspath = bootclasspath;
    this.classpath = classpath;
  }

  /**
   * java ...Compiler output input minSdkVersion mainDexClasses bootclasspath [classpathEntries]+
   */
  public static void main(String[] args) throws Throwable {
    try {
      int argIndex = 0;
      Path outputDir = Paths.get(args[argIndex++]);
      Path input = Paths.get(args[argIndex++]);
      int minSdkVersion = Integer.parseInt(args[argIndex++]);
      Path mainDexClasses = Paths.get(args[argIndex++]);
      Path bootclasspath = Paths.get(args[argIndex++]);

      List<Path> classpath = new ArrayList<>(args.length - argIndex);
      while (argIndex < args.length) {
        classpath.add(Paths.get(args[argIndex++]));
      }

      D8Compiler compiler = new D8Compiler(minSdkVersion, bootclasspath, classpath);

      List<Path> toMerge = new ArrayList<>(3);

      int intermediateIndex = 0;
      for (Path entry : classpath) {
        Path output = outputDir.resolve(entry.getFileName() + "." + (intermediateIndex++));
        Files.createDirectory(output);
        toMerge.add(output);
        compiler.compile(output, entry);
      }

      Path output = outputDir.resolve("main." + (intermediateIndex++));
      Files.createDirectory(output);
      toMerge.add(output);
      compiler.compile(output, input);

      compiler.merge(outputDir, mainDexClasses, toMerge);
    } finally {
      // Terminate pool threads to prevent the VM to wait on then before exiting.
      pool.shutdown();
    }
  }

  private void compile(Path output, Path input) throws Throwable {
    D8Command.Builder builder =
        D8Command.builder()
            // Compile in debug and merge in release to assert access to both modes
            .setMode(CompilationMode.DEBUG)
            .setMinApiLevel(minSdkVersion)
            .setIntermediate(true)
            .setEnableDesugaring(true)
            .setOutputPath(output);

    builder.addLibraryResourceProvider(CachingArchiveClassFileProvider.getProvider(bootclasspath));

    for (Path entry : classpath) {
      builder.addClasspathResourceProvider(CachingArchiveClassFileProvider.getProvider(entry));
    }

    if (Files.isRegularFile(input)) {
      builder.setOutputMode(OutputMode.Indexed);
      builder.addProgramFiles(input);
    } else {
      builder.setOutputMode(OutputMode.FilePerInputClass);
      Files.walkFileTree(input, new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes)
            throws IOException {
          builder.addClassProgramData(Files.readAllBytes(path));
          return FileVisitResult.CONTINUE;
        }
      });
    }

    D8.run(builder.build(), pool);
  }

  private void merge(Path outputDir, Path mainDexClasses,
      List<Path> toMerge) throws IOException, CompilationException {
    D8Command.Builder merger = D8Command.builder();
    merger.setEnableDesugaring(false);

    for (Path mergeInput : toMerge) {
      Files.walkFileTree(mergeInput, new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes)
            throws IOException {
          merger.addDexProgramData(Files.readAllBytes(path));
          return FileVisitResult.CONTINUE;
        }
      });
    }
    if (mainDexClasses != null) {
      merger.addMainDexListFiles(mainDexClasses);
    }
    merger.setMinApiLevel(minSdkVersion)
        .setMode(CompilationMode.RELEASE)
        .setOutputPath(outputDir)
        .setEnableDesugaring(false)
        .setIntermediate(false);
    D8.run(merger.build());
  }
}
