/*
 * 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.command;

import com.facebook.buck.android.AndroidPlatformTarget;
import com.facebook.buck.event.BuckEventBus;
import com.facebook.buck.event.ConsoleEvent;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.java.JavaPackageFinder;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.HasBuildTarget;
import com.facebook.buck.rules.ActionGraph;
import com.facebook.buck.rules.ArtifactCache;
import com.facebook.buck.rules.BuildContext;
import com.facebook.buck.rules.BuildDependencies;
import com.facebook.buck.rules.BuildEngine;
import com.facebook.buck.rules.BuildEvent;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleSuccess;
import com.facebook.buck.rules.ImmutableBuildContext;
import com.facebook.buck.step.DefaultStepRunner;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.StepFailedException;
import com.facebook.buck.step.TargetDevice;
import com.facebook.buck.timing.Clock;
import com.facebook.buck.util.Console;
import com.facebook.buck.util.ExceptionWithHumanReadableMessage;
import com.facebook.buck.util.HumanReadableException;
import com.facebook.buck.util.environment.Platform;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.io.Files;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;

import java.io.Closeable;
import java.io.IOException;
import java.nio.file.Path;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;

import javax.annotation.Nullable;

public class Build implements Closeable {

  private static final Predicate<Optional<BuildRuleSuccess>> RULES_FAILED_PREDICATE =
      new Predicate<Optional<BuildRuleSuccess>>() {
        @Override
        public boolean apply(Optional<BuildRuleSuccess> input) {
          return !input.isPresent();
        }
      };

  private final ActionGraph actionGraph;

  private final ExecutionContext executionContext;

  private final ArtifactCache artifactCache;

  private final BuildEngine buildEngine;

  private final DefaultStepRunner stepRunner;

  private final JavaPackageFinder javaPackageFinder;

  private final BuildDependencies buildDependencies;

  private final Clock clock;

  /** Not set until {@link #executeBuild(Iterable, boolean)} is invoked. */
  @Nullable
  private BuildContext buildContext;

  /**
   * @param buildDependencies How to include dependencies when building rules.
   */
  public Build(
      ActionGraph actionGraph,
      Optional<TargetDevice> targetDevice,
      ProjectFilesystem projectFilesystem,
      Supplier<AndroidPlatformTarget> androidPlatformTargetSupplier,
      BuildEngine buildEngine,
      ArtifactCache artifactCache,
      ListeningExecutorService service,
      JavaPackageFinder javaPackageFinder,
      Console console,
      long defaultTestTimeoutMillis,
      boolean isCodeCoverageEnabled,
      boolean isDebugEnabled,
      BuildDependencies buildDependencies,
      BuckEventBus eventBus,
      Platform platform,
      ImmutableMap<String, String> environment,
      ObjectMapper objectMapper,
      Clock clock) {
    this.actionGraph = actionGraph;

    this.executionContext = ExecutionContext.builder()
        .setProjectFilesystem(projectFilesystem)
        .setConsole(console)
        .setAndroidPlatformTargetSupplier(androidPlatformTargetSupplier)
        .setTargetDevice(targetDevice)
        .setDefaultTestTimeoutMillis(defaultTestTimeoutMillis)
        .setCodeCoverageEnabled(isCodeCoverageEnabled)
        .setDebugEnabled(isDebugEnabled)
        .setEventBus(eventBus)
        .setPlatform(platform)
        .setEnvironment(environment)
        .setJavaPackageFinder(javaPackageFinder)
        .setObjectMapper(objectMapper)
        .build();
    this.artifactCache = artifactCache;
    this.buildEngine = buildEngine;
    this.stepRunner = new DefaultStepRunner(executionContext, service);
    this.javaPackageFinder = javaPackageFinder;
    this.buildDependencies = buildDependencies;
    this.clock = clock;
  }

  public ActionGraph getActionGraph() {
    return actionGraph;
  }

  public ExecutionContext getExecutionContext() {
    return executionContext;
  }

  /** Returns null until {@link #executeBuild(Iterable, boolean)} is invoked. */
  @Nullable
  public BuildContext getBuildContext() {
    return buildContext;
  }

  /**
   * If {@code isKeepGoing} is false, then this returns a future that succeeds only if all of
   * {@code rulesToBuild} build successfully. Otherwise, this returns a future that should always
   * succeed, even if individual rules fail to build. In that case, a failed build rule is indicated
   * by a {@code null} value in the corresponding position in the iteration order of
   * {@code rulesToBuild}.
   * @param targetish The targets to build. All targets in this iterable must be unique.
   */
  @SuppressWarnings("PMD.EmptyCatchBlock")
  public LinkedHashMap<BuildRule, Optional<BuildRuleSuccess>> executeBuild(
      Iterable<? extends HasBuildTarget> targetish,
      boolean isKeepGoing)
      throws IOException, StepFailedException, ExecutionException, InterruptedException {
    buildContext = ImmutableBuildContext.builder()
        .setActionGraph(actionGraph)
        .setStepRunner(stepRunner)
        .setProjectFilesystem(executionContext.getProjectFilesystem())
        .setClock(clock)
        .setArtifactCache(artifactCache)
        .setJavaPackageFinder(javaPackageFinder)
        .setEventBus(executionContext.getBuckEventBus())
        .setAndroidBootclasspathSupplier(BuildContext.createBootclasspathSupplier(
            executionContext.getAndroidPlatformTargetSupplier()))
        .setBuildDependencies(buildDependencies)
        .setBuildId(executionContext.getBuildId())
        .putAllEnvironment(executionContext.getEnvironment())
        .build();

    ImmutableSet<BuildTarget> targetsToBuild = FluentIterable.from(targetish)
        .transform(HasBuildTarget.TO_TARGET)
        .toSet();

    // It is important to use this logic to determine the set of rules to build rather than
    // build.getActionGraph().getNodesWithNoIncomingEdges() because, due to graph enhancement,
    // there could be disconnected subgraphs in the DependencyGraph that we do not want to build.
    ImmutableList<BuildRule> rulesToBuild = ImmutableList.copyOf(
        FluentIterable
            .from(targetsToBuild)
            .transform(new Function<HasBuildTarget, BuildRule>() {
                         @Override
                         public BuildRule apply(HasBuildTarget hasBuildTarget) {
                           return Preconditions.checkNotNull(
                               actionGraph.findBuildRuleByTarget(hasBuildTarget.getBuildTarget()));
                         }
                       })
            .toSet());

    // Calculate and post the number of rules that need to built.
    int numRules = getNumRulesToBuild(targetsToBuild, actionGraph);
    getExecutionContext().getBuckEventBus().post(
        BuildEvent.ruleCountCalculated(
            targetsToBuild,
            numRules));


    List<ListenableFuture<BuildRuleSuccess>> futures = FluentIterable.from(rulesToBuild)
        .transform(
        new Function<BuildRule, ListenableFuture<BuildRuleSuccess>>() {
          @Override
          public ListenableFuture<BuildRuleSuccess> apply(BuildRule rule) {
            return buildEngine.build(buildContext, rule);
          }
        }).toList();

    // Get the Future representing the build and then block until everything is built.
    ListenableFuture<List<BuildRuleSuccess>> buildFuture;
    if (isKeepGoing) {
      buildFuture = Futures.successfulAsList(futures);
    } else {
      buildFuture = Futures.allAsList(futures);
    }

    List<BuildRuleSuccess> results;
    try {
      results = buildFuture.get();
    } catch (InterruptedException e) {
      try {
        buildFuture.cancel(true);
      } catch (CancellationException ignored) {
        // Rethrow original InterruptedException instead.
      }
      Thread.currentThread().interrupt();
      throw e;
    }

    // Insertion order matters
    LinkedHashMap<BuildRule, Optional<BuildRuleSuccess>> resultBuilder = new LinkedHashMap<>();

    Preconditions.checkState(rulesToBuild.size() == results.size());
    for (int i = 0, len = rulesToBuild.size(); i < len; i++) {
      BuildRule rule = rulesToBuild.get(i);
      BuildRuleSuccess success = results.get(i);
      resultBuilder.put(rule, Optional.fromNullable(success));
    }

    return resultBuilder;
  }

  public int executeAndPrintFailuresToConsole(
      Iterable<? extends HasBuildTarget> targetsish,
      boolean isKeepGoing,
      Console console,
      Optional<Path> pathToBuildReport) throws InterruptedException {
    int exitCode;

    try {
      LinkedHashMap<BuildRule, Optional<BuildRuleSuccess>> ruleToResult = executeBuild(
          targetsish,
          isKeepGoing);

      BuildReport buildReport = new BuildReport(ruleToResult);

      if (isKeepGoing) {
        String buildReportText = buildReport.generateForConsole(console.getAnsi());
        // Remove trailing newline from build report.
        buildReportText = buildReportText.substring(0, buildReportText.length() - 1);
        executionContext.getBuckEventBus().post(ConsoleEvent.info(buildReportText));
        exitCode = Iterables.any(ruleToResult.values(), RULES_FAILED_PREDICATE) ? 1 : 0;
        if (exitCode != 0) {
          console.printBuildFailure("Not all rules succeeded.");
        }
      } else {
        exitCode = 0;
      }

      if (pathToBuildReport.isPresent()) {
        // Note that pathToBuildReport is an absolute path that may exist outside of the project
        // root, so it is not appropriate to use ProjectFilesystem to write the output.
        String jsonBuildReport = buildReport.generateJsonBuildReport();
        try {
          Files.write(jsonBuildReport, pathToBuildReport.get().toFile(), Charsets.UTF_8);
        } catch (IOException e) {
          e.printStackTrace(console.getStdErr());
          exitCode = 1;
        }
      }
    } catch (IOException e) {
      console.printBuildFailureWithoutStacktrace(e);
      exitCode = 1;
    } catch (StepFailedException e) {
      console.printBuildFailureWithoutStacktrace(e);
      exitCode = e.getExitCode();
    } catch (ExecutionException e) {
      // This is likely a checked exception that was caught while building a build rule.
      Throwable cause = e.getCause();
      if (cause instanceof HumanReadableException) {
        throw ((HumanReadableException) cause);
      } else if (cause instanceof ExceptionWithHumanReadableMessage) {
        throw new HumanReadableException((ExceptionWithHumanReadableMessage) cause);
      } else {
        if (cause instanceof RuntimeException) {
          console.printBuildFailureWithStacktrace(e);
        } else {
          console.printBuildFailureWithoutStacktrace(e);
        }
        exitCode = 1;
      }
    }

    return exitCode;
  }

  @Override
  public void close() throws IOException {
    executionContext.close();
  }

  private int getNumRulesToBuild(
      Iterable<BuildTarget> buildTargets,
      final ActionGraph actionGraph) {
    Set<BuildRule> baseBuildRules = FluentIterable
        .from(buildTargets)
        .transform(new Function<HasBuildTarget, BuildRule>() {
                     @Override
                     public BuildRule apply(HasBuildTarget hasBuildTarget) {
                       return Preconditions.checkNotNull(
                           actionGraph.findBuildRuleByTarget(hasBuildTarget.getBuildTarget()));
                     }
                   })
        .toSet();

    Set<BuildRule> allBuildRules = Sets.newHashSet();
    for (BuildRule rule : baseBuildRules) {
      addTransitiveDepsForRule(rule, allBuildRules);
    }
    allBuildRules.addAll(baseBuildRules);
    return allBuildRules.size();
  }

  private static void addTransitiveDepsForRule(
      BuildRule buildRule,
      Set<BuildRule> transitiveDeps) {
    ImmutableSortedSet<BuildRule> deps = buildRule.getDeps();
    if (deps.isEmpty()) {
      return;
    }
    for (BuildRule dep : deps) {
      if (!transitiveDeps.contains(dep)) {
        transitiveDeps.add(dep);
        addTransitiveDepsForRule(dep, transitiveDeps);
      }
    }
  }
}
