// 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.origin.Origin;
import com.android.tools.r8.origin.PathOrigin;
import com.android.tools.r8.utils.AbortException;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.ExceptionDiagnostic;
import com.android.tools.r8.utils.ExceptionUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Reporter;
import com.android.tools.r8.utils.StringDiagnostic;
import java.nio.file.NoSuchFileException;
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;

/**
 * Base class for commands and command builders for applications/tools which take an Android
 * application sources (and optional main-dex list) as input.
 *
 * <p>For concrete builders, see for example {@link D8Command.Builder} and {@link
 * R8Command.Builder}.
 */
@Keep
public abstract class BaseCommand {

  private final boolean printHelp;
  private final boolean printVersion;

  private final AndroidApp app;

  BaseCommand(boolean printHelp, boolean printVersion) {
    this.printHelp = printHelp;
    this.printVersion = printVersion;
    // All other fields are initialized with stub/invalid values.
    this.app = null;
  }

  BaseCommand(AndroidApp app) {
    assert app != null;
    this.app = app;
    // Print options are not set.
    printHelp = false;
    printVersion = false;
  }

  public boolean isPrintHelp() {
    return printHelp;
  }

  public boolean isPrintVersion() {
    return printVersion;
  }

  // Internal access to the input resources.
  AndroidApp getInputApp() {
    return app;
  }

  // Internal access to the internal options.
  abstract InternalOptions getInternalOptions();

  abstract static class InputFileOrigin extends PathOrigin {
    private final String inputType;

    public InputFileOrigin(String inputType, Path file) {
      super(file);
      this.inputType = inputType;
    }

    @Override
    public String part() {
      return inputType + " '" + super.part() + "'";
    }
  }

  private static class ProgramInputOrigin extends InputFileOrigin {

    public ProgramInputOrigin(Path file) {
      super("program input", file);
    }
  }

  static class LibraryInputOrigin extends InputFileOrigin {

    public LibraryInputOrigin(Path file) {
      super("library input", file);
    }
  }

  /**
   * Base builder for commands.
   *
   * @param <C> Command the builder is building, e.g., {@link R8Command} or {@link D8Command}.
   * @param <B> Concrete builder extending this base, e.g., {@link R8Command.Builder} or {@link
   *     D8Command.Builder}.
   */
  @Keep
  public abstract static class Builder<C extends BaseCommand, B extends Builder<C, B>> {

    private final Reporter reporter;
    private boolean printHelp = false;
    private boolean printVersion = false;
    private final AndroidApp.Builder app;

    List<Path> programFiles = new ArrayList<>();

    Builder() {
      this(AndroidApp.builder());
    }

    Builder(DiagnosticsHandler handler) {
      this(AndroidApp.builder(new Reporter(handler)));
    }

    Builder(AndroidApp.Builder builder) {
      this.app = builder;
      this.reporter = builder.getReporter();
    }

    abstract B self();

    /**
     * Build the final command.
     *
     * <p>Building the command will complete the validation of builders state and build the final
     * command. If any errors occur during validation or building the errors are reported to the
     * associated diagnostics handler and a {@link CompilationFailedException} exception is thrown.
     */
    public final C build() throws CompilationFailedException {
      Box<C> box = new Box<>(null);
      ExceptionUtils.withCompilationHandler(
          reporter,
          () -> {
            validate();
            box.set(makeCommand());
            reporter.failIfPendingErrors();
          });
      return box.get();
    }

    // Helper to construct the actual command. Called as part of {@link build()}.
    abstract C makeCommand();

    // Internal accessor for the application resources.
    AndroidApp.Builder getAppBuilder() {
      return app;
    }

    /** Add program file resources. */
    public B addProgramFiles(Path... files) {
      addProgramFiles(Arrays.asList(files));
      return self();
    }

    Reporter getReporter() {
      return reporter;
    }

    /** Add program file resources. */
    public B addProgramFiles(Collection<Path> files) {
      guard(
          () -> {
            for (Path path : files) {
              try {
                app.addProgramFile(path);
                programFiles.add(path);
              } catch (CompilationError e) {
                error(new ProgramInputOrigin(path), e);
              }
            }
          });
      return self();
    }

    /** Add a resource provider for program resources. */
    public B addProgramResourceProvider(ProgramResourceProvider programProvider) {
      app.addProgramResourceProvider(programProvider);
      return self();
    }

    /** Add library file resource provider. */
    public B addLibraryResourceProvider(ClassFileResourceProvider provider) {
      guard(() -> getAppBuilder().addLibraryResourceProvider(provider));
      return self();
    }

    /** Add library file resources. */
    public B addLibraryFiles(Path... files) {
      addLibraryFiles(Arrays.asList(files));
      return self();
    }

    /** Add library file resources. */
    public B addLibraryFiles(Collection<Path> files) {
      guard(
          () -> {
            for (Path path : files) {
              try {
                app.addLibraryFile(path);
              } catch (CompilationError e) {
                error(new LibraryInputOrigin(path), e);
              }
            }
          });
      return self();
    }

    /** Add classpath file resources. */
    public B addClasspathFiles(Path... files) {
      guard(() -> Arrays.stream(files).forEach(this::addClasspathFile));
      return self();
    }

    /** Add classpath file resources. */
    public B addClasspathFiles(Collection<Path> files) {
      guard(() -> files.forEach(this::addClasspathFile));
      return self();
    }

    private void addClasspathFile(Path file) {
      guard(() -> getAppBuilder().addClasspathFile(file));
    }

    /** Add classfile resources provider for class-path resources. */
    public B addClasspathResourceProvider(ClassFileResourceProvider provider) {
      guard(() -> getAppBuilder().addClasspathResourceProvider(provider));
      return self();
    }

    /** Add Java-bytecode program-data. */
    public B addClassProgramData(byte[] data, Origin origin) {
      guard(() -> app.addClassProgramData(data, origin));
      return self();
    }

    /** Add Java-bytecode program-data. */
    B addDexProgramData(byte[] data, Origin origin) {
      guard(() -> app.addDexProgramData(data, origin));
      return self();
    }

    /**
     * Add main-dex list files.
     *
     * Each line in each of the files specifies one class to keep in the primary dex file
     * (<code>classes.dex</code>).
     *
     * A class is specified using the following format: "com/example/MyClass.class". That is
     * "/" as separator between package components, and a trailing ".class".
     */
    public B addMainDexListFiles(Path... files) {
      guard(() -> {
        try {
          app.addMainDexListFiles(files);
        } catch (NoSuchFileException e) {
          reporter.error(new StringDiagnostic(
              "Main-dex-list file does not exist", new PathOrigin(Paths.get(e.getFile()))));
        }
      });
      return self();
    }

    /**
     * Add main-dex list files.
     *
     * @see #addMainDexListFiles(Path...)
     */
    public B addMainDexListFiles(Collection<Path> files) {
      guard(
          () -> {
            try {
              app.addMainDexListFiles(files);
            } catch (NoSuchFileException e) {
              reporter.error(
                  new StringDiagnostic(
                      "Main-dex-list file does not exist", new PathOrigin(Paths.get(e.getFile()))));
            }
          });
      return self();
    }

    /**
     * Add main-dex classes.
     *
     * <p>Add classes to keep in the primary dex file (<code>classes.dex</code>).
     *
     * <p>NOTE: The name of the classes is specified using the Java fully qualified names format
     * (e.g. "com.example.MyClass$A"), and <i>not</i> the format used by the main-dex list file.
     */
    public B addMainDexClasses(String... classes) {
      guard(() -> app.addMainDexClasses(classes));
      return self();
    }

    /**
     * Add main-dex classes.
     *
     * Add classes to keep in the primary dex file (<code>classes.dex</code>).
     *
     * NOTE: The name of the classes is specified using the Java fully qualified names format
     * (e.g. "com.example.MyClass"), and <i>not</i> the format used by the main-dex list file.
     */
    public B addMainDexClasses(Collection<String> classes) {
      guard(() -> app.addMainDexClasses(classes));
      return self();
    }

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

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

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

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

    /** Signal an error. */
    public void error(Diagnostic diagnostic) {
      reporter.error(diagnostic);
    }

    /**
     * Signal an error and throw {@link AbortException}.
     *
     * @throws AbortException always.
     */
    public RuntimeException fatalError(Diagnostic diagnostic) {
      return reporter.fatalError(diagnostic);
    }

    // Internal helper for compat tools to make them ignore DEX code in input archives.
    void setIgnoreDexInArchive(boolean value) {
      guard(() -> app.setIgnoreDexInArchive(value));
    }

    // Helper that validates the command content. Called as part of {@link build()}.
    void validate() {}

    // Helper to signify an error.
    void error(Origin origin, Throwable throwable) {
      reporter.error(new ExceptionDiagnostic(throwable, origin));
    }

    // Helper to guard and handle exceptions.
    void guard(Runnable action) {
      try {
        action.run();
      } catch (CompilationError e) {
        reporter.error(e.toStringDiagnostic());
      } catch (AbortException e) {
        // Error was reported and exception will be thrown by build.
      }
    }

  }
}
