/*
 * 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.step.ExecutionContext;
import com.facebook.buck.step.Step;
import com.facebook.buck.util.Escaper;
import com.facebook.buck.util.ProcessExecutor;
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.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;

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 {

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

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

  /**
   * This is set if {@link #shouldRecordStdout()} returns {@code true} when the command is
   * executed.
   */
  @Nullable
  private String stdOut;

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

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

  protected ShellStep(@Nullable File workingDirectory) {
    this.workingDirectory = workingDirectory;
  }

  /**
   * 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;
  }

  /**
   * @return whether stdout should be recorded when this command is executed. If this returns
   *     {@code true}, then the stdout will be available via {@link #getStdOut()}.
   */
  protected boolean shouldRecordStdout() {
    return false;
  }

  @Override
  public int execute(ExecutionContext context) {
    // Kick off a Process in which this ShellCommand will be run.
    ProcessBuilder processBuilder = new ProcessBuilder(getShellCommand(context));

    // Add environment variables, if appropriate.
    if (!getEnvironmentVariables(context).isEmpty()) {
      Map<String, String> environment = processBuilder.environment();
      environment.putAll(getEnvironmentVariables(context));
    }

    if (workingDirectory != null) {
      processBuilder.directory(workingDirectory);
    } else {
      processBuilder.directory(context.getProjectDirectoryRoot());
    }

    Process process;
    try {
      startTime = System.currentTimeMillis();
      process = processBuilder.start();
    } catch (IOException e) {
      e.printStackTrace(context.getStdErr());
      return 1;
    }

    int exitCode = interactWithProcess(context, process);
    endTime = System.currentTimeMillis();
    return exitCode;
  }

  @VisibleForTesting
  int interactWithProcess(ExecutionContext context, Process process) {
    boolean shouldRecordStdOut = shouldRecordStdout();
    boolean shouldPrintStdErr = shouldPrintStdErr(context);
    ProcessExecutor executor = context.getProcessExecutor();
    ProcessExecutor.Result result = executor.execute(process,
        shouldRecordStdOut,
        shouldPrintStdErr,
        context.getVerbosity() == Verbosity.SILENT);
    if (shouldRecordStdOut) {
      this.stdOut = result.getStdOut();
    }
    return result.getExitCode();
  }

  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);
    }
    return shellCommandArgs;
  }

  /**
   * 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(workingDirectory.getPath()),
          shellCommand);
    }
  }

  /**
   * @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(ExecutionContext context) {
    return context.getVerbosity().shouldPrintOutput();
  }

  /**
   * 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();
  }

  /**
   * @return the stdout of this ShellCommand or throws an exception if the stdout was not recorded
   */
  public final String getStdOut() {
    Preconditions.checkNotNull(this.stdOut, "stdout was not set: " +
    		"shouldRecordStdout() must return true and execute() must have been invoked");
    return this.stdOut;
  }

  @VisibleForTesting
  final void setStdOut(String stdOut) {
    this.stdOut = stdOut;
  }
}
