/*
 * Copyright 2012-present Facebook, Inc.
 *
 * 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.facebook.buck.shell;

import com.facebook.buck.event.ConsoleEvent;
import com.facebook.buck.log.Logger;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.Step;
import com.facebook.buck.util.Escaper;
import com.facebook.buck.util.ImmutableProcessExecutorParams;
import com.facebook.buck.util.ProcessExecutor;
import com.facebook.buck.util.ProcessExecutor.Option;
import com.facebook.buck.util.ProcessExecutorParams;
import com.facebook.buck.util.Verbosity;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Nullable;

public abstract class ShellStep implements Step {

  private static final Logger LOG = Logger.get(ShellStep.class);

  /** Defined lazily by {@link #getShellCommand(com.facebook.buck.step.ExecutionContext)}. */
  @Nullable
  private ImmutableList<String> shellCommandArgs;

  /** If specified, working directory will be different from project root. **/
  @Nullable
  protected final File workingDirectory;

  /**
   * This is set if {@link #shouldPrintStdout(Verbosity)} returns {@code true} when the command is
   * executed.
   */
  private Optional<String> stdout;

  /**
   * This is set if {@link #shouldPrintStderr(Verbosity)} returns {@code true} when the command is
   * executed.
   */
  private Optional<String> stderr;

  private long startTime = 0L;
  private long endTime = 0L;

  protected ShellStep() {
    this(/* workingDirectory */ null);
  }

  protected ShellStep(@Nullable File workingDirectory) {
    this.workingDirectory = workingDirectory;
    this.stdout = Optional.absent();
    this.stderr = Optional.absent();
  }

  /**
   * Get the working directory for this command.
   * @return working directory specified on construction
   *         ({@code null} if project directory will be used).
   */
  @Nullable
  @VisibleForTesting
  public File getWorkingDirectory() {
    return workingDirectory;
  }

  @Override
  public int execute(ExecutionContext context) throws InterruptedException {
    // Kick off a Process in which this ShellCommand will be run.
    ImmutableProcessExecutorParams.Builder builder = ImmutableProcessExecutorParams.builder();

    builder.setCommand(getShellCommand(context));
    Map<String, String> environment = Maps.newHashMap();
    setProcessEnvironment(context, environment);
    builder.setEnvironment(environment);

    if (workingDirectory != null) {
      builder.setDirectory(workingDirectory);
    } else {
      builder.setDirectory(context.getProjectDirectoryRoot().toAbsolutePath().toFile());
    }

    Optional<String> stdin = getStdin(context);
    if (stdin.isPresent()) {
      builder.setRedirectInput(ProcessBuilder.Redirect.PIPE);
    }

    int exitCode;
    try {
      startTime = System.currentTimeMillis();
      exitCode = launchAndInteractWithProcess(context, builder.build());
    } catch (IOException e) {
      e.printStackTrace(context.getStdErr());
      exitCode = 1;
    }

    endTime = System.currentTimeMillis();

    return exitCode;
  }

  @VisibleForTesting
  void setProcessEnvironment(ExecutionContext context, Map<String, String> environment) {

    // Replace environment with client environment.
    environment.clear();
    environment.putAll(context.getEnvironment());

    // Add extra environment variables for step, if appropriate.
    if (!getEnvironmentVariables(context).isEmpty()) {
      environment.putAll(getEnvironmentVariables(context));
    }
  }

  /**
   * @return the exit code interpreted from the {@code result}.
   */
  @SuppressWarnings("unused")
  protected int getExitCodeFromResult(ExecutionContext context, ProcessExecutor.Result result) {
    return result.getExitCode();
  }

  @VisibleForTesting
  int launchAndInteractWithProcess(ExecutionContext context, ProcessExecutorParams params)
      throws InterruptedException, IOException {
    ImmutableSet.Builder<Option> options = ImmutableSet.builder();

    addOptions(context, options);

    ProcessExecutor executor = context.getProcessExecutor();
    ProcessExecutor.Result result = executor.launchAndExecute(
        params,
        options.build(),
        getStdin(context),
        getTimeout());
    stdout = result.getStdout();
    stderr = result.getStderr();

    Verbosity verbosity = context.getVerbosity();
    if (stdout.isPresent() && !stdout.get().isEmpty() && shouldPrintStdout(verbosity)) {
      context.postEvent(ConsoleEvent.info("%s", stdout.get()));
    }
    if (stderr.isPresent() && !stderr.get().isEmpty() && shouldPrintStderr(verbosity)) {
      context.postEvent(ConsoleEvent.warning("%s", stderr.get()));
    }

    return getExitCodeFromResult(context, result);
  }

  protected void addOptions(
      ExecutionContext context,
      ImmutableSet.Builder<Option> options) {
    if (shouldFlushStdOutErrAsProgressIsMade(context.getVerbosity())) {
      options.add(Option.PRINT_STD_OUT);
      options.add(Option.PRINT_STD_ERR);
    }
    if (context.getVerbosity() == Verbosity.SILENT) {
      options.add(Option.IS_SILENT);
    }
  }

  public long getDuration() {
    Preconditions.checkState(startTime > 0);
    Preconditions.checkState(endTime > 0);
    return endTime - startTime;
  }

  /**
   * This method is idempotent.
   * @return the shell command arguments
   */
  public final ImmutableList<String> getShellCommand(ExecutionContext context) {
    if (shellCommandArgs == null) {
      shellCommandArgs = getShellCommandInternal(context);
      LOG.debug("Command: %s", Joiner.on(" ").join(shellCommandArgs));
    }
    return shellCommandArgs;
  }

  @SuppressWarnings("unused")
  protected Optional<String> getStdin(ExecutionContext context) {
    return Optional.absent();
  }

  /**
   * Implementations of this method should not have any observable side-effects.
   */
  @VisibleForTesting
  protected abstract ImmutableList<String> getShellCommandInternal(ExecutionContext context);

  @Override
  public final String getDescription(ExecutionContext context) {
    // Get environment variables for this command as VAR1=val1 VAR2=val2... etc., with values
    // quoted as necessary.
    Iterable<String> env = Iterables.transform(getEnvironmentVariables(context).entrySet(),
        new Function<Entry<String, String>, String>() {
          @Override
          public String apply(Entry<String, String> e) {
            return String.format("%s=%s", e.getKey(), Escaper.escapeAsBashString(e.getValue()));
          }
    });

    // Quote the arguments to the shell command as needed (this applies to $0 as well
    // e.g. if we run '/path/a b.sh' quoting is needed).
    Iterable<String> cmd = Iterables.transform(getShellCommand(context), Escaper.BASH_ESCAPER);

    String shellCommand = Joiner.on(" ").join(Iterables.concat(env, cmd));
    if (getWorkingDirectory() == null) {
      return shellCommand;
    } else {
      // If the ShellCommand has a specific working directory, set through ProcessBuilder, then
      // this is what the user might type in a shell to get the same behavior. The (...) syntax
      // introduces a subshell in which the command is only executed if cd was successful.
      return String.format("(cd %s && %s)",
          Escaper.escapeAsBashString(Preconditions.checkNotNull(workingDirectory).getPath()),
          shellCommand);
    }
  }

  /**
   * Returns the environment variables to include when running this {@link ShellStep}.
   * <p>
   * By default, this method returns an empty map.
   * @param context that may be useful when determining environment variables to include.
   */
  public ImmutableMap<String, String> getEnvironmentVariables(ExecutionContext context) {
    return ImmutableMap.of();
  }

  /**
   * @param verbosity is provided in case that affects what should be printed.
   * @return whether the stdout of the shell command, when executed, should be printed to the stderr
   *     of the specified {@link ExecutionContext}. If {@code false}, stdout will only be printed on
   *     error and only if verbosity is set to standard information.
   */
  protected boolean shouldPrintStdout(Verbosity verbosity) {
    return false;
  }

  /**
   * @return the stdout of this ShellCommand or throws an exception if the stdout was not recorded
   */
  public final String getStdout() {
    Preconditions.checkState(
        this.stdout.isPresent(),
        "stdout was not set: shouldPrintStdout() must return false and execute() must " +
        "have been invoked");
    return this.stdout.get();
  }

  /**
   * @return whether the stderr of the shell command, when executed, should be printed to the stderr
   *     of the specified {@link ExecutionContext}. If {@code false}, stderr will only be printed on
   *     error and only if verbosity is set to standard information.
   */
  protected boolean shouldPrintStderr(Verbosity verbosity) {
    return verbosity.shouldPrintOutput();
  }

  /**
   * @return the stderr of this ShellCommand or throws an exception if the stderr was not recorded
   */
  public final String getStderr() {
    Preconditions.checkState(
        this.stderr.isPresent(),
        "stderr was not set: shouldPrintStdErr() must return false and execute() must " +
        "have been invoked");
    return this.stderr.get();
  }

  /**
   * By default, the output written to stdout and stderr will be buffered into individual
   * {@link ByteArrayOutputStream}s and then converted into strings for easier consumption. This
   * means that output from both streams that would normally be interleaved will now be displayed
   * separately.
   * <p>
   * To disable this behavior and print to stdout and stderr directly, this method should be
   * overridden to return {@code true}.
   */
  @SuppressWarnings("unused")
  protected boolean shouldFlushStdOutErrAsProgressIsMade(Verbosity verbosity) {
    return false;
  }

  /**
   * @return an optional timeout to apply to the step.
   */
  protected Optional<Long> getTimeout() {
    return Optional.absent();
  }

}
