// Copyright (c) 2020, 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.graph.DexItemFactory;
import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibraryConfiguration;
import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibraryConfigurationParser;
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.InternalOptions;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringDiagnostic;
import com.google.common.collect.ImmutableSet;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;

/**
 * Immutable command structure for an invocation of the {@link BackportedMethodList} tool.
 *
 * <p>To build a BackportedMethodList command use the {@link BackportedMethodListCommand.Builder}
 * class. For example:
 *
 * <pre>
 *   BackportedMethodListCommand command = BackportedMethodListCommand.builder()
 *     .setMinApiLevel(apiLevel)
 *     .setOutputPath(Paths.get("methods-list.txt"))
 *     .build();
 * </pre>
 */
@Keep
public class BackportedMethodListCommand {

  private final boolean printHelp;
  private final boolean printVersion;
  private final Reporter reporter;
  private final int minApiLevel;
  private final DesugaredLibraryConfiguration desugaredLibraryConfiguration;
  private final AndroidApp app;
  private final StringConsumer backportedMethodListConsumer;
  private final DexItemFactory factory;

  public boolean isPrintHelp() {
    return printHelp;
  }

  public boolean isPrintVersion() {
    return printVersion;
  }

  Reporter getReporter() {
    return reporter;
  }

  public int getMinApiLevel() {
    return minApiLevel;
  }

  public DesugaredLibraryConfiguration getDesugaredLibraryConfiguration() {
    return desugaredLibraryConfiguration;
  }

  public StringConsumer getBackportedMethodListConsumer() {
    return backportedMethodListConsumer;
  }

  AndroidApp getInputApp() {
    return app;
  }

  private BackportedMethodListCommand(boolean printHelp, boolean printVersion) {
    this.printHelp = printHelp;
    this.printVersion = printVersion;
    this.reporter = new Reporter();
    this.minApiLevel = -1;
    this.desugaredLibraryConfiguration = null;
    this.app = null;
    this.backportedMethodListConsumer = null;
    this.factory = null;
  }

  private BackportedMethodListCommand(
      Reporter reporter,
      int minApiLevel,
      DesugaredLibraryConfiguration desugaredLibraryConfiguration,
      AndroidApp app,
      StringConsumer backportedMethodListConsumer,
      DexItemFactory factory) {
    this.printHelp = false;
    this.printVersion = false;
    this.reporter = reporter;
    this.minApiLevel = minApiLevel;
    this.desugaredLibraryConfiguration = desugaredLibraryConfiguration;
    this.app = app;
    this.backportedMethodListConsumer = backportedMethodListConsumer;
    this.factory = factory;
  }

  InternalOptions getInternalOptions() {
    InternalOptions options = new InternalOptions(factory, getReporter());
    options.minApiLevel = AndroidApiLevel.getAndroidApiLevel(minApiLevel);
    options.desugaredLibraryConfiguration = desugaredLibraryConfiguration;
    return options;
  }

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

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

  public static Builder parse(String[] args) {
    final Set<String> OPTIONS_WITH_PARAMETER =
        ImmutableSet.of("--output", "--min-api", "--desugared-lib", "--lib");

    boolean hasDefinedApiLevel = false;
    Builder builder = builder();
    for (int i = 0; i < args.length; i++) {
      String arg = args[i].trim();
      String nextArg = null;
      if (OPTIONS_WITH_PARAMETER.contains(arg)) {
        if (++i < args.length) {
          nextArg = args[i];
        } else {
          builder.error(new StringDiagnostic("Missing parameter for " + args[i - 1] + "."));
          break;
        }
      }
      if (arg.equals("--help")) {
        builder.setPrintHelp(true);
      } else if (arg.equals("--version")) {
        builder.setPrintVersion(true);
      } else if (arg.equals("--min-api")) {
        if (hasDefinedApiLevel) {
          builder.error(new StringDiagnostic("Cannot set multiple --min-api options"));
        } else {
          parseMinApi(builder, nextArg);
          hasDefinedApiLevel = true;
        }
      } else if (arg.equals("--desugared-lib")) {
        builder.addDesugaredLibraryConfiguration(StringResource.fromFile(Paths.get(nextArg)));
      } else if (arg.equals("--lib")) {
        builder.addLibraryFiles(Paths.get(nextArg));
      } else if (arg.equals("--output")) {
        builder.setOutputPath(Paths.get(nextArg));
      } else {
        builder.error(new StringDiagnostic("Unknown option: " + arg));
      }
    }
    return builder;
  }

  private static void parseMinApi(Builder builder, String minApiString) {
    int minApi;
    try {
      minApi = Integer.parseInt(minApiString);
    } catch (NumberFormatException e) {
      builder.error(new StringDiagnostic("Invalid argument to --min-api: " + minApiString));
      return;
    }
    if (minApi < 1) {
      builder.error(new StringDiagnostic("Invalid argument to --min-api: " + minApiString));
      return;
    }
    builder.setMinApiLevel(minApi);
  }

  @Keep
  public static class Builder {

    private final Reporter reporter;
    private int minApiLevel = AndroidApiLevel.B.getLevel();
    private List<StringResource> desugaredLibraryConfigurationResources = new ArrayList<>();
    private final AndroidApp.Builder app;
    private StringConsumer backportedMethodListConsumer;
    private boolean printHelp = false;
    private boolean printVersion = false;

    private Builder() {
      this(new DiagnosticsHandler() {});
    }

    private Builder(DiagnosticsHandler diagnosticsHandler) {
      this.app = AndroidApp.builder();
      this.reporter = new Reporter(diagnosticsHandler);
    }

    /**
     * Set the minimum API level for the application compiled.
     *
     * <p>The tool will only report backported methods which are not present at this API level.
     *
     * <p>The default is 1 if never set.
     */
    public Builder setMinApiLevel(int minApiLevel) {
      if (minApiLevel <= 0) {
        reporter.error(new StringDiagnostic("Invalid minApiLevel: " + minApiLevel));
      } else {
        this.minApiLevel = minApiLevel;
      }
      return this;
    }

    public int getMinApiLevel() {
      return minApiLevel;
    }

    /** Desugared library configuration */
    public Builder addDesugaredLibraryConfiguration(StringResource configuration) {
      desugaredLibraryConfigurationResources.add(configuration);
      return this;
    }

    /** Desugared library configuration */
    public Builder addDesugaredLibraryConfiguration(String configuration) {
      return addDesugaredLibraryConfiguration(
          StringResource.fromString(configuration, Origin.unknown()));
    }

    /** The compilation SDK library (android.jar) */
    public Builder addLibraryResourceProvider(ClassFileResourceProvider provider) {
      app.addLibraryResourceProvider(provider);
      return this;
    }

    /** The compilation SDK library (android.jar) */
    public Builder addLibraryFiles(Path... files) {
      addLibraryFiles(Arrays.asList(files));
      return this;
    }

    /** The compilation SDK library (android.jar) */
    public Builder addLibraryFiles(Collection<Path> files) {
      for (Path path : files) {
        app.addLibraryFile(path);
      }
      return this;
    }

    DesugaredLibraryConfiguration getDesugaredLibraryConfiguration(DexItemFactory factory) {
      if (desugaredLibraryConfigurationResources.isEmpty()) {
        return DesugaredLibraryConfiguration.empty();
      }
      if (desugaredLibraryConfigurationResources.size() > 1) {
        reporter.fatalError("Only one desugared library configuration is supported.");
      }
      StringResource desugaredLibraryConfigurationResource =
          desugaredLibraryConfigurationResources.get(0);
      DesugaredLibraryConfigurationParser libraryParser =
          new DesugaredLibraryConfigurationParser(factory, null, false, getMinApiLevel());
      return libraryParser.parse(desugaredLibraryConfigurationResource);
    }

    /** Output file for the backported method list */
    public Builder setOutputPath(Path outputPath) {
      backportedMethodListConsumer =
          new StringConsumer.FileConsumer(outputPath) {
            @Override
            public void accept(String string, DiagnosticsHandler handler) {
              super.accept(string, handler);
              super.accept(System.lineSeparator(), handler);
            }
          };
      return this;
    }

    /** Consumer receiving the the backported method list */
    public Builder setConsumer(StringConsumer consumer) {
      this.backportedMethodListConsumer = consumer;
      return this;
    }

    /** True if the print-help flag is enabled. */
    public boolean isPrintHelp() {
      return printHelp;
    }

    /** Set the value of the print-help flag. */
    public Builder setPrintHelp(boolean printHelp) {
      this.printHelp = printHelp;
      return this;
    }

    /** True if the print-version flag is enabled. */
    public boolean isPrintVersion() {
      return printVersion;
    }

    /** Set the value of the print-version flag. */
    public Builder setPrintVersion(boolean printVersion) {
      this.printVersion = printVersion;
      return this;
    }

    private void error(Diagnostic diagnostic) {
      reporter.error(diagnostic);
    }

    public BackportedMethodListCommand build() {
      AndroidApp library = app.build();
      if (!desugaredLibraryConfigurationResources.isEmpty()
          && library.getLibraryResourceProviders().isEmpty()) {
        reporter.error(
            new StringDiagnostic("With desugared library configuration a library is required"));
      }

      if (isPrintHelp() || isPrintVersion()) {
        return new BackportedMethodListCommand(isPrintHelp(), isPrintVersion());
      }

      if (backportedMethodListConsumer == null) {
        backportedMethodListConsumer =
            new StringConsumer() {
              @Override
              public void accept(String string, DiagnosticsHandler handler) {
                System.out.println(string);
              }

              @Override
              public void finished(DiagnosticsHandler handler) {}
            };
      }
      DexItemFactory factory = new DexItemFactory();
      return new BackportedMethodListCommand(
          reporter,
          minApiLevel,
          getDesugaredLibraryConfiguration(factory),
          library,
          backportedMethodListConsumer,
          factory);
    }
  }
}
