// Copyright 2016 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.devtools.build.lib.shell;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.jni.JniLoader;
import com.google.devtools.build.lib.util.OS;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import javax.annotation.Nullable;

/**
 * A builder class that starts a subprocess.
 */
public class SubprocessBuilder {
  /**
   * What to do with an output stream of the process.
   */
  public enum StreamAction {
    /** Redirect to a file */
    REDIRECT,

    /** Discard. */
    DISCARD,

    /** Stream back to the parent process using an output stream. */
    STREAM
  }

  private final SubprocessFactory factory;
  private ImmutableList<String> argv;
  private ImmutableMap<String, String> env;
  private StreamAction stdoutAction;
  private File stdoutFile;
  private StreamAction stderrAction;
  private File stderrFile;
  private File workingDirectory;
  private long timeoutMillis;
  private boolean redirectErrorStream;

  static SubprocessFactory defaultFactory = subprocessFactoryImplementation();

  private static SubprocessFactory subprocessFactoryImplementation() {
    if (JniLoader.isJniAvailable() && OS.getCurrent() == OS.WINDOWS) {
      return WindowsSubprocessFactory.INSTANCE;
    } else {
      return JavaSubprocessFactory.INSTANCE;
    }
  }

  /**
   * Sets the default factory class for creating subprocesses. Passing {@code null} resets it to the
   * initial state.
   */
  @VisibleForTesting
  public static void setDefaultSubprocessFactory(SubprocessFactory factory) {
    SubprocessBuilder.defaultFactory =
        factory != null ? factory : subprocessFactoryImplementation();
  }

  public SubprocessBuilder() {
    this(defaultFactory);
  }

  public SubprocessBuilder(SubprocessFactory factory) {
    stdoutAction = StreamAction.STREAM;
    stderrAction = StreamAction.STREAM;
    this.factory = factory;
  }

  /**
   * Returns the complete argv, including argv0.
   *
   * <p>argv[0] is either absolute (e.g. "/foo/bar" or "c:/foo/bar.exe"), or is a single file name
   * (no directory component, e.g. "true" or "cmd.exe"). It might be non-normalized though (e.g.
   * "/foo/../bar/./baz").
   */
  public ImmutableList<String> getArgv() {
    return argv;
  }

  /**
   * Sets the argv, including argv[0], that is, the binary to execute.
   *
   * <p>argv[0] must be either absolute (e.g. "/foo/bar" or "c:/foo/bar.exe"), or a single file name
   * (no directory component, e.g. "true" or "cmd.exe") which should be on the OS-specific search
   * path (PATH on Unixes, Windows-specific lookup paths on Windows).
   *
   * @throws IllegalArgumentException if argv is empty, or its first element (which becomes
   *     this.argv[0]) is neither an absolute path nor just a single file name
   */
  @CanIgnoreReturnValue
  public SubprocessBuilder setArgv(ImmutableList<String> argv) {
    this.argv = Preconditions.checkNotNull(argv);
    Preconditions.checkArgument(!this.argv.isEmpty());
    File argv0 = new File(this.argv.get(0));
    Preconditions.checkArgument(
        argv0.isAbsolute() || argv0.getParent() == null,
        "argv[0] = '%s'; it should be either absolute or just a single file name"
            + " (no directory component)",
        this.argv.get(0));
    return this;
  }

  public ImmutableMap<String, String> getEnv() {
    return env;
  }

  /**
   * Sets the environment passed to the child process. If null, inherit the environment of the
   * server.
   */
  @CanIgnoreReturnValue
  public SubprocessBuilder setEnv(@Nullable Map<String, String> env) {
    this.env = env == null ? null : ImmutableMap.copyOf(env);
    return this;
  }

  public StreamAction getStdout() {
    return stdoutAction;
  }

  public File getStdoutFile() {
    return stdoutFile;
  }

  /**
   * Tells the object what to do with stdout: either stream as a {@code InputStream} or discard.
   *
   * <p>It can also be redirected to a file using {@link #setStdout(File)}.
   */
  @CanIgnoreReturnValue
  public SubprocessBuilder setStdout(StreamAction action) {
    if (action == StreamAction.REDIRECT) {
      throw new IllegalStateException();
    }
    this.stdoutAction = action;
    this.stdoutFile = null;
    return this;
  }

  /**
   * Sets the file stdout is appended to. If null, the stdout will be available as an input stream
   * on the resulting object representing the process.
   */
  @CanIgnoreReturnValue
  public SubprocessBuilder setStdout(File file) {
    this.stdoutAction = StreamAction.REDIRECT;
    this.stdoutFile = file;
    return this;
  }

  @CanIgnoreReturnValue
  public SubprocessBuilder setTimeoutMillis(long timeoutMillis) {
    this.timeoutMillis = timeoutMillis;
    return this;
  }

  public long getTimeoutMillis() {
    return timeoutMillis;
  }

  public StreamAction getStderr() {
    return stderrAction;
  }

  public File getStderrFile() {
    return stderrFile;
  }

  /**
   * Tells the object what to do with stderr: either stream as a {@code InputStream} or discard.
   *
   * <p>It can also be redirected to a file using {@link #setStderr(File)}.
   */
  @CanIgnoreReturnValue
  public SubprocessBuilder setStderr(StreamAction action) {
    if (action == StreamAction.REDIRECT) {
      throw new IllegalStateException();
    }
    this.stderrAction = action;
    this.stderrFile = null;
    return this;
  }

  /**
   * Sets the file stderr is appended to. If null, the stderr will be available as an input stream
   * on the resulting object representing the process. When {@code redirectErrorStream} is set to
   * True, this method has no effect.
   */
  @CanIgnoreReturnValue
  public SubprocessBuilder setStderr(File file) {
    this.stderrAction = StreamAction.REDIRECT;
    this.stderrFile = file;
    return this;
  }

  /**
   * Tells whether this process builder merges standard error and standard output.
   *
   * @return this process builder's {@code redirectErrorStream} property
   */
  public boolean redirectErrorStream() {
    return redirectErrorStream;
  }

  /**
   * Sets whether this process builder merges standard error and standard output.
   *
   * <p>If this property is {@code true}, then any error output generated by subprocesses
   * subsequently started by this object's {@link #start()} method will be merged with the standard
   * output, so that both can be read using the {@link Subprocess#getInputStream()} method. This
   * makes it easier to correlate error messages with the corresponding output. The initial value is
   * {@code false}.
   */
  @CanIgnoreReturnValue
  public SubprocessBuilder redirectErrorStream(boolean redirectErrorStream) {
    this.redirectErrorStream = redirectErrorStream;
    return this;
  }

  public File getWorkingDirectory() {
    return workingDirectory;
  }

  /** Sets the current working directory. If null, it will be that of this process. */
  @CanIgnoreReturnValue
  public SubprocessBuilder setWorkingDirectory(File workingDirectory) {
    this.workingDirectory = workingDirectory;
    return this;
  }

  public Subprocess start() throws IOException {
    return factory.create(this);
  }
}
