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

import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.graph.AssemblyWriter;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexByteCodeWriter;
import com.android.tools.r8.graph.DexByteCodeWriter.OutputStreamProvider;
import com.android.tools.r8.graph.SmaliWriter;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.origin.CommandLineOrigin;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.ConsumerUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.ThreadUtils;
import com.android.tools.r8.utils.Timing;
import java.io.Closeable;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.function.Consumer;

public class Disassemble {
  public static class DisassembleCommand extends BaseCommand {

    private final Path outputPath;
    private final StringResource proguardMap;

    public static class Builder extends BaseCommand.Builder<DisassembleCommand, Builder> {

      private Path outputPath = null;
      private Path proguardMapFile = null;
      private boolean useSmali = false;
      private boolean allInfo = false;
      private boolean noCode = false;
      private boolean useIr;

      @Override
      Builder self() {
        return this;
      }

      public Builder setProguardMapFile(Path path) {
        proguardMapFile = path;
        return this;
      }

      public Path getOutputPath() {
        return outputPath;
      }

      public Builder setOutputPath(Path outputPath) {
        this.outputPath = outputPath;
        return this;
      }

      public Builder setAllInfo(boolean allInfo) {
        this.allInfo = allInfo;
        return this;
      }

      public Builder setUseSmali(boolean useSmali) {
        this.useSmali = useSmali;
        return this;
      }

      public Builder setUseIr(boolean useIr) {
        this.useIr = useIr;
        return this;
      }

      public Builder setNoCode(boolean noCode) {
        this.noCode = noCode;
        return this;
      }

      @Override
      protected DisassembleCommand makeCommand() {
        // If printing versions ignore everything else.
        if (isPrintHelp() || isPrintVersion()) {
          return new DisassembleCommand(isPrintHelp(), isPrintVersion());
        }
        return new DisassembleCommand(
            getAppBuilder().build(),
            getOutputPath(),
            proguardMapFile == null ? null : StringResource.fromFile(proguardMapFile),
            allInfo,
            useSmali,
            useIr,
            noCode);
      }
    }

    static final String USAGE_MESSAGE =
        "Usage: disasm [options] <input-files>\n"
            + " where <input-files> are dex files\n"
            + " and options are:\n"
            + "  --all                       # Include all information in disassembly.\n"
            + "  --smali                     # Disassemble using smali syntax.\n"
            + "  --ir                        # Print IR before and after optimization.\n"
            + "  --nocode                    # No printing of code objects.\n"
            + "  --pg-map <file>             # Proguard map <file> for mapping names.\n"
            + "  --pg-map-charset <charset>  # Charset for Proguard map file.\n"
            + "  --output                    # Specify a file or directory to write to.\n"
            + "  --version                   # Print the version of r8.\n"
            + "  --help                      # Print this message.";

    private final boolean allInfo;
    private final boolean useSmali;
    private final boolean useIr;
    private final boolean noCode;

    public static Builder builder() {
      return new Builder();
    }

    public static Builder parse(String[] args) {
      Builder builder = builder();
      parse(args, builder);
      return builder;
    }

    private static void parse(String[] args, Builder builder) {
      for (int i = 0; i < args.length; i++) {
        String arg = args[i].trim();
        if (arg.length() == 0) {
          continue;
        } else if (arg.equals("--help")) {
          builder.setPrintHelp(true);
        } else if (arg.equals("--version")) {
          builder.setPrintVersion(true);
        } else if (arg.equals("--all")) {
          builder.setAllInfo(true);
        } else if (arg.equals("--smali")) {
          builder.setUseSmali(true);
        } else if (arg.equals("--ir")) {
          builder.setUseIr(true);
        } else if (arg.equals("--nocode")) {
          builder.setNoCode(true);
        } else if (arg.equals("--pg-map")) {
          builder.setProguardMapFile(Paths.get(args[++i]));
        } else if (arg.equals("--pg-map-charset")) {
          String charset = args[++i];
          try {
            Charset.forName(charset);
          } catch (UnsupportedCharsetException e) {
            builder.getReporter().error(
                new StringDiagnostic(
                    "Unsupported charset: " + charset + "." + System.lineSeparator()
                        + "Supported charsets are: "
                        + String.join(", ", Charset.availableCharsets().keySet()),
                CommandLineOrigin.INSTANCE));
          }
        } else if (arg.equals("--output")) {
          String outputPath = args[++i];
          builder.setOutputPath(Paths.get(outputPath));
        } else {
          if (arg.startsWith("--")) {
            builder.getReporter().error(new StringDiagnostic("Unknown option: " + arg,
                CommandLineOrigin.INSTANCE));
          }
          builder.addProgramFiles(Paths.get(arg));
        }
      }
    }

    private DisassembleCommand(
        AndroidApp inputApp,
        Path outputPath,
        StringResource proguardMap,
        boolean allInfo,
        boolean useSmali,
        boolean useIr,
        boolean noCode) {
      super(inputApp);
      this.outputPath = outputPath;
      this.proguardMap = proguardMap;
      this.allInfo = allInfo;
      this.useSmali = useSmali;
      this.useIr = useIr;
      this.noCode = noCode;
    }

    private DisassembleCommand(boolean printHelp, boolean printVersion) {
      super(printHelp, printVersion);
      outputPath = null;
      proguardMap = null;
      allInfo = false;
      useSmali = false;
      useIr = false;
      noCode = false;
    }

    public Path getOutputPath() {
      return outputPath;
    }

    public boolean useSmali() {
      return useSmali;
    }

    public boolean useIr() {
      return useIr;
    }

    public boolean noCode() {
      return noCode;
    }

    @Override
    InternalOptions getInternalOptions() {
      InternalOptions internal = new InternalOptions();
      internal.useSmaliSyntax = useSmali;
      internal.readDebugSetFileEvent = true;
      return internal;
    }
  }

  public static void main(String[] args)
      throws IOException, ExecutionException, CompilationFailedException {
    DisassembleCommand.Builder builder = DisassembleCommand.parse(args);
    DisassembleCommand command = builder.build();
    if (command.isPrintHelp()) {
      System.out.println(DisassembleCommand.USAGE_MESSAGE);
      return;
    }
    if (command.isPrintVersion()) {
      System.out.println("Disassemble (R8) " + Version.LABEL);
      return;
    }
    disassemble(command);
  }

  public static void disassemble(DisassembleCommand command)
      throws IOException, ExecutionException {
    AndroidApp app = command.getInputApp();
    InternalOptions options = command.getInternalOptions();
    Box<Future<ClassNameMapper>> readMapFuture = new Box<>();
    try (OutputWriter outputWriter = getOutputWriter(command)) {
      for (ProgramResource computeAllProgramResource : app.computeAllProgramResources()) {
        disassembleResource(
            command, outputWriter, computeAllProgramResource, readMapFuture, options);
      }
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  private static OutputWriter getOutputWriter(DisassembleCommand command) throws Exception {
    if (command.getOutputPath() == null) {
      return SystemOutOutputWriter.create();
    } else if (Files.isDirectory(command.getOutputPath())) {
      return DirectoryWriter.create(
          command.getOutputPath(),
          command.useSmali() ? SmaliWriter.getFileEnding() : AssemblyWriter.getFileEnding());
    } else {
      return FileWriter.create(command.getOutputPath());
    }
  }

  private static void disassembleResource(
      DisassembleCommand command,
      OutputWriter outputWriter,
      ProgramResource programResource,
      Box<Future<ClassNameMapper>> readMapFuture,
      InternalOptions options)
      throws IOException {
    ExecutorService executor = ThreadUtils.getExecutorService(options);
    try {
      DexApplication application =
          new ApplicationReader(
                  AndroidApp.builder()
                      .addProgramResourceProvider(() -> Collections.singletonList(programResource))
                      .build(),
                  options,
                  Timing.empty(),
                  readMapFuture)
              .read(command.proguardMap, executor);
      DexByteCodeWriter writer =
          command.useSmali()
              ? new SmaliWriter(application, options)
              : new AssemblyWriter(
                  application, options, command.allInfo, command.useIr(), !command.noCode());
      if (outputWriter.extractMarkers()) {
        writer.writeMarkers(
            outputWriter.outputStreamProvider(application.getProguardMap()).get(null));
      }
      writer.write(
          outputWriter.outputStreamProvider(application.getProguardMap()), outputWriter.closer());
    } finally {
      executor.shutdown();
    }
  }

  private interface OutputWriter extends Closeable {
    boolean extractMarkers();

    OutputStreamProvider outputStreamProvider(ClassNameMapper classNameMapper);

    Consumer<PrintStream> closer();
  }

  private static class SystemOutOutputWriter implements OutputWriter {

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

    @Override
    public OutputStreamProvider outputStreamProvider(ClassNameMapper classNameMapper) {
      return clazz -> System.out;
    }

    @Override
    public Consumer<PrintStream> closer() {
      return ConsumerUtils.emptyConsumer();
    }

    static SystemOutOutputWriter create() {
      return new SystemOutOutputWriter();
    }

    @Override
    public void close() throws IOException {
      // Intentionally empty.
    }
  }

  private static class DirectoryWriter implements OutputWriter {

    private final Path parent;
    private final String fileEnding;

    public DirectoryWriter(Path parent, String fileEnding) {
      this.parent = parent;
      this.fileEnding = fileEnding;
    }

    @Override
    public boolean extractMarkers() {
      return false;
    }

    @Override
    public OutputStreamProvider outputStreamProvider(ClassNameMapper classNameMapper) {
      return DexByteCodeWriter.oneFilePerClass(classNameMapper, parent, fileEnding);
    }

    @Override
    public Consumer<PrintStream> closer() {
      return PrintStream::close;
    }

    private static DirectoryWriter create(Path path, String fileEnding) throws IOException {
      Path parent = path.getParent();
      if (parent != null) {
        Files.createDirectories(parent);
      }
      return new DirectoryWriter(path, fileEnding);
    }

    @Override
    public void close() throws IOException {
      // Intentionally empty.
    }
  }

  private static class FileWriter implements OutputWriter {

    private final PrintStream fileStream;

    private FileWriter(PrintStream fileStream) {
      this.fileStream = fileStream;
    }

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

    @Override
    public OutputStreamProvider outputStreamProvider(ClassNameMapper classNameMapper) {
      return clazz -> fileStream;
    }

    @Override
    public Consumer<PrintStream> closer() {
      // Per entry close per disassembled class is ignored to keep the print stream open until
      // everything has been written.
      return ConsumerUtils.emptyConsumer();
    }

    private static FileWriter create(Path path) throws IOException {
      Path parent = path.getParent();
      if (parent != null) {
        Files.createDirectories(parent);
      }
      return new FileWriter(new PrintStream(Files.newOutputStream(path)));
    }

    @Override
    public void close() throws IOException {
      fileStream.flush();
      fileStream.close();
    }
  }
}
