// Copyright (c) 2017, the Rex 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 static com.android.tools.r8.utils.StringUtils.quote;

import com.android.tools.r8.dex.ApplicationReader;
import com.android.tools.r8.dex.Marker;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.MarkerInfoConsumerDataImpl;
import com.android.tools.r8.utils.MarkerInfoImpl;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.Timing;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;

/**
 * A tool to extract markers generated by the R8 compiler and related tools.
 *
 * <p>The tool is run by defining a consumer and then building the command, such as:
 *
 * <pre>
 *   ExtractMarker.run(ExtractMarkerCommand.builder()
 *       .addProgramFiles(inputPathA, inputPathB)
 *       .setMarkerInfoConsumer(new MyInfoConsumer())
 *       .build());
 * </pre>
 */
@Keep
public class ExtractMarker {

  private static class MarkerInfoPrintConsumer implements MarkerInfoConsumer {

    private final PrintStream stream;

    public MarkerInfoPrintConsumer(PrintStream stream) {
      this.stream = stream;
    }

    private void printRow(Origin inputOrigin, String rawMarker) {
      stream.print(inputOrigin.toString());
      stream.print(": ");
      stream.print(rawMarker);
      stream.println();
    }

    @Override
    public void acceptMarkerInfo(MarkerInfoConsumerData data) {
      if (data.hasMarkers()) {
        for (MarkerInfo marker : data.getMarkers()) {
          printRow(data.getInputOrigin(), marker.getRawEncoding());
        }
      } else {
        printRow(data.getInputOrigin(), quote("no marker"));
      }
    }

    @Override
    public void finished() {}
  }

  private static class InterceptedException extends RuntimeException {
    private final CompilationFailedException compilationFailedException;

    private InterceptedException(CompilationFailedException e) {
      this.compilationFailedException = e;
    }
  }

  private static Collection<Marker> extractMarker(AndroidApp app) throws IOException {
    InternalOptions options = new InternalOptions();
    options.skipReadingDexCode = true;
    options.setMinApiLevel(AndroidApiLevel.P);
    DexApplication dexApp = new ApplicationReader(app, options, new Timing("ExtractMarker")).read();
    return dexApp.dexItemFactory.extractMarkers();
  }

  private static void extractForConsumer(
      MarkerInfoConsumer consumer, Reporter reporter, Origin origin, AndroidApp.Builder builder) {
    List<Marker> markers = new ArrayList<>();
    try {
      ExceptionUtils.withCompilationHandler(
          reporter, () -> markers.addAll(extractMarker(builder.build())));
    } catch (CompilationFailedException e) {
      throw new InterceptedException(e);
    }
    // Ensure the markers are sorted, so we have deterministic callback/print order.
    markers.sort(Comparator.comparing(Marker::toString));
    List<MarkerInfo> infos = ListUtils.map(markers, MarkerInfoImpl::new);
    consumer.acceptMarkerInfo(new MarkerInfoConsumerDataImpl(origin, infos));
  }

  /**
   * Main API entry for the extract marker tool.
   *
   * @param command Extract marker command specification.
   */
  public static void run(ExtractMarkerCommand command) throws CompilationFailedException {
    MarkerInfoConsumer consumer = command.getMarkerInfoConsumer();
    Reporter reporter = new Reporter(command.getDiagnosticsHandler());
    try {
      command.forEachEntry(
          (path, origin) ->
              extractForConsumer(
                  consumer, reporter, origin, AndroidApp.builder().addProgramFile(path)),
          (data, origin) ->
              extractForConsumer(
                  consumer, reporter, origin, AndroidApp.builder().addDexProgramData(data, origin)),
          (data, origin) ->
              extractForConsumer(
                  consumer,
                  reporter,
                  origin,
                  AndroidApp.builder().addClassProgramData(data, origin)));
    } catch (InterceptedException e) {
      throw e.compilationFailedException;
    }
  }

  private static void run(String[] args) throws CompilationFailedException {
    PrintStream out = System.out;
    ExtractMarkerCommand.Builder builder = ExtractMarkerCommand.parse(args);
    MarkerInfoConsumer consumer = new MarkerInfoPrintConsumer(out);
    ExtractMarkerCommand command = builder.setMarkerInfoConsumer(consumer).build();
    if (command.isPrintHelp()) {
      System.out.println(ExtractMarkerCommand.USAGE_MESSAGE);
      return;
    }
    run(command);
  }

  /**
   * Command-line entry to the extract marker tool.
   *
   * <p>See {@link ExtractMarkerCommand#USAGE_MESSAGE} or run with {@code --help} for usage
   * information.
   */
  public static void main(String[] args) throws Exception {
    ExceptionUtils.withMainProgramHandler(() -> run(args));
  }
}
