// 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.keepanno.annotations.KeepForApi;
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}.
 */
@KeepForApi
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}.
   */
  @KeepForApi
  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(createReporter(handler)));
    }

    static Reporter createReporter(DiagnosticsHandler handler) {
      if (handler instanceof Reporter) {
        return (Reporter) handler;
      } else {
        return 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.
      }
    }

  }
}
