// 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.errors.CompilationError;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.OffOrAuto;
import com.android.tools.r8.utils.OutputMode;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;

/**
 * Immutable command structure for an invocation of the {@code D8} compiler.
 *
 * <p>To build a D8 command use the {@code D8Command.Builder} class. For example:
 *
 * <pre>
 *   D8Command command = D8Command.builder()
 *     .addProgramFiles(path1, path2)
 *     .setMode(CompilationMode.RELEASE)
 *     .build();
 * </pre>
 */
public class D8Command extends BaseCompilerCommand {

  /**
   * Builder for constructing a D8Command.
   */
  public static class Builder extends BaseCompilerCommand.Builder<D8Command, Builder> {

    private boolean intermediate = false;

    protected Builder(boolean ignoreDexInArchive) {
      super(CompilationMode.DEBUG, ignoreDexInArchive);
    }

    protected Builder() {
      super(CompilationMode.DEBUG);
    }

    private Builder(AndroidApp app) {
      super(app, CompilationMode.DEBUG);
    }

    /** Add classpath file resources. */
    public Builder addClasspathFiles(Path... files) throws IOException {
      getAppBuilder().addClasspathFiles(files);
      return self();
    }

    /** Add classpath file resources. */
    public Builder addClasspathFiles(Collection<Path> files) throws IOException {
      getAppBuilder().addClasspathFiles(files);
      return self();
    }

    public Builder addClasspathResourceProvider(ClassFileResourceProvider provider) {
      getAppBuilder().addClasspathResourceProvider(provider);
      return self();
    }

    public Builder setIntermediate(boolean value) {
      this.intermediate = value;
      return self();
    }

    @Override
    Builder self() {
      return this;
    }

    protected void validate() throws CompilationException {
      super.validate();
      if (getAppBuilder().hasMainDexList() && intermediate) {
        throw new CompilationException(
            "Option --main-dex-list cannot be used with --intermediate");
      }
    }

    /**
     * Build the final D8Command.
     */
    @Override
    public D8Command build() throws CompilationException {
      if (isPrintHelp() || isPrintVersion()) {
        return new D8Command(isPrintHelp(), isPrintVersion());
      }

      validate();
      return new D8Command(
          getAppBuilder().build(),
          getOutputPath(),
          getOutputMode(),
          getMode(),
          getMinApiLevel(),
          intermediate);
    }
  }

  static final String USAGE_MESSAGE = String.join("\n", ImmutableList.of(
      "Usage: d8 [options] <input-files>",
      " where <input-files> are any combination of dex, class, zip, jar, or apk files",
      " and options are:",
      "  --debug                 # Compile with debugging information (default).",
      "  --release               # Compile without debugging information.",
      "  --output <file>         # Output result in <outfile>.",
      "                          # <file> must be an existing directory or a zip file.",
      "  --lib <file>            # Add <file> as a library resource.",
      "  --classpath <file>      # Add <file> as a classpath resource.",
      "  --min-api               # Minimum Android API level compatibility",
      "  --intermediate          # Compile an intermediate result intended for later",
      "                          # merging.",
      "  --file-per-class        # Produce a separate dex file per class",
      "  --main-dex-list <file>  # List of classes to place in the primary dex file.",
      "  --version               # Print the version of d8.",
      "  --help                  # Print this message."));

  private boolean intermediate = false;

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

  // Internal builder to start from an existing AndroidApp.
  static Builder builder(AndroidApp app) {
    return new Builder(app);
  }

  public static Builder parse(String[] args) throws CompilationException, IOException {
    CompilationMode modeSet = null;
    Path outputPath = null;
    Builder builder = builder();
    try {
      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("--debug")) {
          if (modeSet == CompilationMode.RELEASE) {
            throw new CompilationException("Cannot compile in both --debug and --release mode.");
          }
          builder.setMode(CompilationMode.DEBUG);
          modeSet = CompilationMode.DEBUG;
        } else if (arg.equals("--release")) {
          if (modeSet == CompilationMode.DEBUG) {
            throw new CompilationException("Cannot compile in both --debug and --release mode.");
          }
          builder.setMode(CompilationMode.RELEASE);
          modeSet = CompilationMode.RELEASE;
        } else if (arg.equals("--file-per-class")) {
          builder.setOutputMode(OutputMode.FilePerClass);
        } else if (arg.equals("--output")) {
          String output = args[++i];
          if (outputPath != null) {
            throw new CompilationException(
                "Cannot output both to '" + outputPath.toString() + "' and '" + output + "'");
          }
          outputPath = Paths.get(output);
        } else if (arg.equals("--lib")) {
          builder.addLibraryFiles(Paths.get(args[++i]));
        } else if (arg.equals("--classpath")) {
          builder.addClasspathFiles(Paths.get(args[++i]));
        } else if (arg.equals("--main-dex-list")) {
          builder.addMainDexListFiles(Paths.get(args[++i]));
        } else if (arg.equals("--min-api")) {
          builder.setMinApiLevel(Integer.valueOf(args[++i]));
        } else if (arg.equals("--intermediate")) {
          builder.setIntermediate(true);
        } else {
          if (arg.startsWith("--")) {
            throw new CompilationException("Unknown option: " + arg);
          }
          builder.addProgramFiles(Paths.get(arg));
        }
      }
      return builder.setOutputPath(outputPath);
    } catch (CompilationError e) {
      throw new CompilationException(e.getMessage(), e);
    }
  }

  private D8Command(
      AndroidApp inputApp,
      Path outputPath,
      OutputMode outputMode,
      CompilationMode mode,
      int minApiLevel,
      boolean intermediate) {
    super(inputApp, outputPath, outputMode, mode, minApiLevel);
    this.intermediate = intermediate;
  }

  private D8Command(boolean printHelp, boolean printVersion) {
    super(printHelp, printVersion);
  }

  @Override
  InternalOptions getInternalOptions() {
    InternalOptions internal = new InternalOptions(new DexItemFactory());
    assert !internal.debug;
    internal.debug = getMode() == CompilationMode.DEBUG;
    internal.minimalMainDex = internal.debug;
    internal.minApiLevel = getMinApiLevel();
    internal.intermediate = intermediate;
    // Assert and fixup defaults.
    assert !internal.skipMinification;
    internal.skipMinification = true;
    assert internal.useTreeShaking;
    internal.useTreeShaking = false;
    assert internal.interfaceMethodDesugaring == OffOrAuto.Off;
    assert internal.tryWithResourcesDesugaring == OffOrAuto.Off;
    assert internal.inlineAccessors;
    internal.inlineAccessors = false;
    assert internal.removeSwitchMaps;
    internal.removeSwitchMaps = false;
    assert internal.outline.enabled;
    internal.outline.enabled = false;
    internal.outputMode = getOutputMode();
    return internal;
  }
}
