/*
 * Copyright 2014-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.cxx;

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.FunctionLineProcessorThread;
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.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.nio.file.Path;

/**
 * A step that compiles and assembles C/C++ sources.
 */
public class CxxCompileStep implements Step {

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

  private final ImmutableList<String> compilerPrefix;
  private final ImmutableList<String> flags;
  private final Path output;
  private final Path input;
  private final Optional<DebugPathSanitizer> sanitizer;

  public CxxCompileStep(
      ImmutableList<String> compilerPrefix,
      ImmutableList<String> flags,
      Path output,
      Path input,
      Optional<DebugPathSanitizer> sanitizer) {
    this.compilerPrefix = compilerPrefix;
    this.flags = flags;
    this.output = output;
    this.input = input;
    this.sanitizer = sanitizer;
  }

  @VisibleForTesting
  protected Function<String, String> createErrorLineProcessor(final Path workingDir) {
    return CxxDescriptionEnhancer.createErrorMessagePathProcessor(
        new Function<String, String>() {
          @Override
          public String apply(String original) {
            return sanitizer.isPresent() ?
                sanitizer.get().restore(Optional.of(workingDir), original) :
                original;
          }
        });
  }

  @Override
  public String getShortName() {
    return "c++ compile";
  }

  @VisibleForTesting
  protected ImmutableList<String> getCommand() {
    return ImmutableList.<String>builder()
        .addAll(compilerPrefix)
        .add("-c")
        .addAll(flags)
        .add("-o", output.toString())
        .add(input.toString())
        .build();
  }

  @Override
  public int execute(ExecutionContext context) throws InterruptedException {
    LOG.debug("Compiling %s -> %s", input, output);
    ProcessBuilder builder = new ProcessBuilder();
    builder.command(getCommand());
    builder.directory(context.getProjectDirectoryRoot().toAbsolutePath().toFile());
    builder.redirectError(ProcessBuilder.Redirect.PIPE);

    // A forced compilation directory is set in the constructor.  Now, we can't actually
    // force the compiler to embed this into the binary -- all we can do set the PWD environment
    // to variations of the actual current working directory (e.g. /actual/dir or /actual/dir////).
    // So we use this knob to expand the space used to store the compilation directory to the
    // size we need for the compilation directory we really want, then do an in-place
    // find-and-replace to update the compilation directory after the fact.
    if (sanitizer.isPresent()) {
      builder.environment().put(
          "PWD",
          sanitizer.get().getExpandedPath(context.getProjectDirectoryRoot().toAbsolutePath()));
    }

    try {
      LOG.debug(
          "Running command (pwd=%s): %s",
          builder.directory(),
          Joiner.on(' ').join(Iterables.transform(builder.command(), Escaper.BASH_ESCAPER)));

      // Start the process.
      Process process = builder.start();

      // We buffer error messages in memory, as these are typically small.
      ByteArrayOutputStream error = new ByteArrayOutputStream();

      // Open the temp file to write the intermediate output to and also fire up managed threads
      // to process the stdout and stderr lines from the preprocess command.
      try (FunctionLineProcessorThread errorProcessor =
               new FunctionLineProcessorThread(
                   process.getErrorStream(),
                   error,
                   createErrorLineProcessor(context.getProjectDirectoryRoot().toAbsolutePath()))) {
        errorProcessor.start();
      }

      // Wait for the process to finish, and grab it's exit code.
      int exitCode = process.waitFor();

      // If we generated any error output, print that to the console.
      String err = new String(error.toByteArray());
      if (!err.isEmpty()) {
        context.getConsole().printErrorText(err);
      }

      if (exitCode != 0) {
        LOG.warn("Error %d compiling %s: %s", exitCode, input, err);
      }

      // If the compilation completed successfully, perform the in-place update of the compilation
      // as per above.  This locates the relevant debug section and swaps out the expanded actual
      // compilation directory with the one we really want.
      if (exitCode == 0 && sanitizer.isPresent()) {
        try {
          sanitizer.get().restoreCompilationDirectory(
              context.getProjectDirectoryRoot().toAbsolutePath().resolve(output),
              context.getProjectDirectoryRoot().toAbsolutePath());
        } catch (IOException e) {
          context.logError(e, "error updating compilation directory");
          return 1;
        }
      }

      LOG.warn("Error compiling %s: %s (%d)", input, err, exitCode);

      return exitCode;

    } catch (InterruptedException | InterruptedIOException e) {
      throw new InterruptedException();

    } catch (Exception e) {
      context.getConsole().printBuildFailureWithStacktrace(e);
      return 1;
    }
  }

  @Override
  public String getDescription(ExecutionContext context) {
    return Joiner.on(' ').join(
        FluentIterable.from(getCommand())
            .transform(Escaper.BASH_ESCAPER));
  }

}
