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

import com.facebook.buck.event.BuckEventBus;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.StepFailedException;
import com.facebook.buck.step.StepRunner;
import com.facebook.buck.util.BuckConstant;
import com.facebook.buck.util.DirectoryTraverser;
import com.facebook.buck.util.DirectoryTraversers;
import com.facebook.buck.util.concurrent.MoreFutures;
import com.google.common.annotations.Beta;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.annotation.Nullable;

/**
 * Abstract implementation of a {@link BuildRule} that can be cached. If its current {@link RuleKey}
 * matches the one on disk, then it has no work to do. It should also try to fetch its output from
 * an {@link ArtifactCache} to avoid doing any computation.
 */
@Beta
public abstract class AbstractCachingBuildRule extends AbstractBuildRule
    implements BuildRule {

  private final Buildable buildable;

  /**
   * Lock used to ensure that the logic to kick off a build is performed at most once.
   */
  private final AtomicBoolean hasBuildStarted;

  /**
   * This is the value returned by {@link #build(BuildContext)}.
   * This is initialized by the constructor and marked as final because {@link #build(BuildContext)}
   * must always return the same value.
   */
  private final SettableFuture<BuildRuleSuccess> buildRuleResult;

  private final Function<String, String> pathRelativizer;

  /** @see Buildable#getInputsToCompareToOutput()  */
  private Iterable<InputRule> inputsToCompareToOutputs;

  protected AbstractCachingBuildRule(Buildable buildable, BuildRuleParams params) {
    super(params);
    this.buildable = Preconditions.checkNotNull(buildable);
    this.hasBuildStarted = new AtomicBoolean(false);
    this.buildRuleResult = SettableFuture.create();
    this.pathRelativizer = params.getPathRelativizer();
  }

  protected AbstractCachingBuildRule(BuildRuleParams buildRuleParams) {
    super(buildRuleParams);
    this.hasBuildStarted = new AtomicBoolean(false);
    this.buildRuleResult = SettableFuture.create();
    this.pathRelativizer = buildRuleParams.getPathRelativizer();
    this.buildable = Preconditions.checkNotNull(getBuildable());
  }

  /**
   * This rule is designed to be used for precondition checks in subclasses. For example, before
   * running the tests associated with a build rule, it is reasonable to do a sanity check to
   * ensure that the rule has been built.
   */
  protected final synchronized boolean isRuleBuilt() {
    return MoreFutures.isSuccess(buildRuleResult);
  }

  @Override
  public BuildRuleSuccess.Type getBuildResultType() {
    Preconditions.checkState(isRuleBuilt());
    try {
      return buildRuleResult.get().getType();
    } catch (InterruptedException | ExecutionException e) {
      throw new RuntimeException(e);
    }
  }

  @Override
  public Iterable<InputRule> getInputs() {
    if (inputsToCompareToOutputs == null) {
      inputsToCompareToOutputs = InputRule.inputPathsAsInputRules(
          buildable.getInputsToCompareToOutput(), pathRelativizer);
    }
    return inputsToCompareToOutputs;
  }

  @Override
  public RuleKey.Builder appendToRuleKey(RuleKey.Builder builder) throws IOException {
    // For a rule that lists its inputs via a "srcs" argument, this may seem redundant, but it is
    // not. Here, the inputs are specified as InputRules, which means that the _contents_ of the
    // files will be hashed. In the case of .set("srcs", srcs), the list of strings itself will be
    // hashed. It turns out that we need both of these in order to construct a RuleKey correctly.
    builder = super.appendToRuleKey(builder)
        .setInputs("buck.inputs", getInputs());
    // TODO(simons): Rename this when no Buildables extend this class.
    return buildable.appendDetailsToRuleKey(builder);
  }

  @Override
  public final ListenableFuture<BuildRuleSuccess> build(final BuildContext context) {
    // We use hasBuildStarted as a lock so that we can minimize how much we need to synchronize.
    synchronized(hasBuildStarted) {
      if (hasBuildStarted.get()) {
        return buildRuleResult;
      } else {
        hasBuildStarted.set(true);
      }
    }

    // Build all of the deps first and then schedule a callback for this rule to build itself once
    // all of those rules are done building.
    try {
      // Invoke every dep's build() method and create an uber-ListenableFuture that represents the
      // successful completion of all deps.
      List<ListenableFuture<BuildRuleSuccess>> builtDeps =
          Lists.newArrayListWithCapacity(getDeps().size());
      for (BuildRule dep : getDeps()) {
        builtDeps.add(dep.build(context));
      }
      ListenableFuture<List<BuildRuleSuccess>> allBuiltDeps = Futures.allAsList(builtDeps);

      // Schedule this rule to build itself once all of the deps are built.
      Futures.addCallback(allBuiltDeps,
          new FutureCallback<List<BuildRuleSuccess>>() {

            private final BuckEventBus eventBus = context.getEventBus();

            private final OnDiskBuildInfo onDiskBuildInfo = context.createOnDiskBuildInfoFor(
                getBuildTarget());

            /**
             * It is imperative that:
             * <ol>
             *   <li>The {@link BuildInfoRecorder} is not constructed until all of the
             *       {@link Buildable}'s {@code deps} are guaranteed to be built. This ensures that
             *       the {@link RuleKey} will be available before the {@link BuildInfoRecorder} is
             *       constructed.
             *       <p>
             *       This is why a {@link Supplier} is used.
             *   <li>Only one {@link BuildInfoRecorder} is created per {@link Buildable}. This
             *       ensures that all build-related information for a {@link Buildable} goes though
             *       a single recorder, whose data will be persisted in {@link #onSuccess(List)}.
             *       <p>
             *       This is why {@link Suppliers#memoize(Supplier)} is used.
             * </ol>
             */
            private final Supplier<BuildInfoRecorder> buildInfoRecorder = Suppliers.memoize(
                new Supplier<BuildInfoRecorder>() {
                  @Override
                  public BuildInfoRecorder get() {
                    AbstractBuildRule buildRule = AbstractCachingBuildRule.this;
                    RuleKey ruleKey;
                    RuleKey ruleKeyWithoutDeps;
                    try {
                      ruleKey = buildRule.getRuleKey();
                      ruleKeyWithoutDeps = buildRule.getRuleKeyWithoutDeps();
                    } catch (IOException e) {
                      throw new RuntimeException(e);
                    }

                    return context.createBuildInfoRecorder(
                        buildRule.getBuildTarget(), ruleKey, ruleKeyWithoutDeps);
                  }
                });

            private boolean startOfBuildWasRecordedOnTheEventBus = false;

            @Override
            public void onSuccess(List<BuildRuleSuccess> deps) {
              // Record the start of the build.
              eventBus.post(BuildRuleEvent.started(AbstractCachingBuildRule.this));
              startOfBuildWasRecordedOnTheEventBus = true;

              try {
                BuildResult result = buildOnceDepsAreBuilt(
                    context, onDiskBuildInfo, buildInfoRecorder.get());
                if (result.isSuccess()) {
                  recordBuildRuleSuccess(result);
                } else {
                  recordBuildRuleFailure(result);
                }
              } catch (IOException e) {
                onFailure(e);
              }
            }

            private void recordBuildRuleSuccess(BuildResult result) {
              // Make sure that all of the local files have the same values they would as if the
              // rule had been built locally.
              if (result.success.shouldWriteRecordedMetadataToDiskAfterBuilding()) {
                try {
                  buildInfoRecorder.get().writeMetadataToDisk();
                } catch (IOException e) {
                  onFailure(e);
                }
              }

              // Give the rule a chance to populate its internal data structures now that all of the
              // files should be in a valid state.
              if (result.success.shouldInitializeFromDiskAfterBuilding()) {
                initializeFromDisk(onDiskBuildInfo);
              }

              // Only now that the rule should be in a completely valid state, resolve the future.
              BuildRuleSuccess buildRuleSuccess = new BuildRuleSuccess(
                  AbstractCachingBuildRule.this, result.success);
              buildRuleResult.set(buildRuleSuccess);

              // Do the post to the event bus immediately after the future is set so that the
              // build time measurement is as accurate as possible.
              eventBus.post(BuildRuleEvent.finished(AbstractCachingBuildRule.this,
                  result.status,
                  result.cacheResult,
                  Optional.of(result.success)));

              // Finally, upload to the artifact cache.
              if (result.success.shouldUploadResultingArtifact()) {
                buildInfoRecorder.get().performUploadToArtifactCache(context.getArtifactCache(),
                    eventBus);
              }
            }

            @Override
            public void onFailure(Throwable failure) {
              recordBuildRuleFailure(new BuildResult(failure));
            }

            private void recordBuildRuleFailure(BuildResult result) {
              // TODO(mbolin): Delete all genfiles and metadata, as they are not guaranteed to be
              // valid at this point?

              // Note that startOfBuildWasRecordedOnTheEventBus will be false if onSuccess() was
              // never invoked.
              if (startOfBuildWasRecordedOnTheEventBus) {
                eventBus.post(BuildRuleEvent.finished(AbstractCachingBuildRule.this,
                    result.status,
                    result.cacheResult,
                    Optional.<BuildRuleSuccess.Type>absent()));
              }

              // It seems possible (albeit unlikely) that something could go wrong in
              // recordBuildRuleSuccess() after buildRuleResult has been resolved such that Buck
              // would attempt to resolve the future again, which would fail.
              buildRuleResult.setException(result.failure);
            }
          },
          context.getExecutor());
    } catch (Throwable failure) {
      // This is a defensive catch block: if buildRuleResult is never satisfied, then Buck will
      // hang because a callback that is waiting for this rule's future to complete will never be
      // executed.
      buildRuleResult.setException(failure);
    }

    return buildRuleResult;
  }

  /**
   * This method is invoked once all of this rule's dependencies are built.
   * <p>
   * This method should be executed on a fresh Runnable in BuildContext's ListeningExecutorService,
   * so there is no reason to schedule new work in a new Runnable.
   * <p>
   * All exit paths through this method should resolve {@link #buildRuleResult} before exiting. To
   * that end, this method should never throw an exception, or else Buck will hang waiting for
   * {@link #buildRuleResult} to be resolved.
   */
  private BuildResult buildOnceDepsAreBuilt(final BuildContext context,
      OnDiskBuildInfo onDiskBuildInfo,
      BuildInfoRecorder buildInfoRecorder) throws IOException {
    // Compute the current RuleKey and compare it to the one stored on disk.
    RuleKey ruleKey = getRuleKey();
    Optional<RuleKey> cachedRuleKey = onDiskBuildInfo.getRuleKey();

    // If the RuleKeys match, then there is nothing to build.
    if (ruleKey.equals(cachedRuleKey.orNull())) {
      context.logBuildInfo("[UNCHANGED %s]", getFullyQualifiedName());
      return new BuildResult(BuildRuleSuccess.Type.MATCHING_RULE_KEY, CacheResult.HIT);
    }

    // Deciding whether we need to rebuild is tricky business. We want to rebuild as little as
    // possible while always being sound.
    //
    // For java_library rules that depend only on their first-order deps,
    // they only need to rebuild themselves if any of the following conditions hold:
    // (1) The definition of the build rule has changed.
    // (2) Any of the input files (which includes resources as well as .java files) have changed.
    // (3) The ABI of any of its dependent java_library rules has changed.
    //
    // For other types of build rules, we have to be more conservative when rebuilding. In those
    // cases, we rebuild if any of the following conditions hold:
    // (1) The definition of the build rule has changed.
    // (2) Any of the input files have changed.
    // (3) Any of the RuleKeys of this rule's deps have changed.
    //
    // Because a RuleKey for a rule will change if any of its transitive deps have changed, that
    // means a change in one of the leaves can result in almost all rules being rebuilt, which is
    // slow. Fortunately, we limit the effects of this when building Java code when checking the ABI
    // of deps instead of the RuleKey for deps.
    if (this instanceof AbiRule) {
      AbiRule abiRule = (AbiRule)this;

      RuleKey ruleKeyNoDeps = getRuleKeyWithoutDeps();
      Optional<RuleKey> cachedRuleKeyNoDeps = onDiskBuildInfo.getRuleKeyWithoutDeps();
      if (ruleKeyNoDeps.equals(cachedRuleKeyNoDeps.orNull())) {
        // The RuleKey for the definition of this build rule and its input files has not changed.
        // Therefore, if the ABI of its deps has not changed, there is nothing to rebuild.
        Optional<Sha1HashCode> abiKeyForDeps = abiRule.getAbiKeyForDeps();
        Optional<Sha1HashCode> cachedAbiKeyForDeps = onDiskBuildInfo.getHash(
            AbiRule.ABI_KEY_FOR_DEPS_ON_DISK_METADATA);
        if (abiKeyForDeps.isPresent() && abiKeyForDeps.equals(cachedAbiKeyForDeps)) {
          // Re-copy the ABI metadata.
          // TODO(mbolin): This seems really bad: there could be other metadata to copy, too?
          buildInfoRecorder.addMetadata(
              AbiRule.ABI_KEY_ON_DISK_METADATA,
              onDiskBuildInfo.getValue(AbiRule.ABI_KEY_ON_DISK_METADATA).get());
          buildInfoRecorder.addMetadata(
              AbiRule.ABI_KEY_FOR_DEPS_ON_DISK_METADATA,
              cachedAbiKeyForDeps.get().getHash());
          return new BuildResult(BuildRuleSuccess.Type.MATCHING_DEPS_ABI_AND_RULE_KEY_NO_DEPS,
              CacheResult.HIT);
        }
      }
    }

    // Before deciding to build, check the ArtifactCache.
    // The fetched file is now a ZIP file, so it needs to be unzipped.
    boolean fromCache = tryToFetchArtifactFromBuildCacheAndOverlayOnTopOfProjectFilesystem(
        buildInfoRecorder,
        context.getArtifactCache(),
        context.getProjectRoot());

    // Run the steps to build this rule since it was not found in the cache.
    if (fromCache) {
      return new BuildResult(BuildRuleSuccess.Type.FETCHED_FROM_CACHE, CacheResult.HIT);
    }

    // The only remaining option is to build locally.
    try {
      executeCommandsNowThatDepsAreBuilt(context, onDiskBuildInfo, buildInfoRecorder);
    } catch (IOException | StepFailedException e) {
      return new BuildResult(e);
    }

    // Given that the Buildable has built successfully, record that the output file has been
    // written, assuming it has one.
    // TODO(mbolin): Buildable.getSteps() should use BuildableContext such that Buildable is
    // responsible for invoking recordArtifact() itself. Once that is done, this call to
    // recordArtifact() should be deleted.
    String pathToOutputFile = buildable.getPathToOutputFile();
    if (pathToOutputFile != null && pathToOutputFile.startsWith(BuckConstant.GEN_DIR)) {
      String prefix = BuckConstant.GEN_DIR + '/' + getBuildTarget().getBasePathWithSlash();
      buildInfoRecorder.recordArtifact(pathToOutputFile.substring(prefix.length()));
    }

    return new BuildResult(BuildRuleSuccess.Type.BUILT_LOCALLY, CacheResult.MISS);
  }

  private boolean tryToFetchArtifactFromBuildCacheAndOverlayOnTopOfProjectFilesystem(
      BuildInfoRecorder buildInfoRecorder,
      ArtifactCache artifactCache,
      Path projectRoot) {
    // Create a temp file whose extension must be ".zip" for Filesystems.newFileSystem() to infer
    // that we are creating a zip-based FileSystem.
    File zipFile;
    try {
      zipFile = File.createTempFile(getFullyQualifiedName().replace('/', '_'), ".zip");
    } catch (IOException e) {
      throw new RuntimeException(e);
    }

    // TODO(mbolin): Change ArtifactCache.fetch() so that it returns a File instead of takes one.
    // Then we could download directly from Cassandra into the on-disk cache and unzip it from
    // there.
    boolean isSuccessfulFetch = buildInfoRecorder.fetchArtifactForBuildable(zipFile, artifactCache);
    if (!isSuccessfulFetch) {
      return false;
    }

    // We unzip the file in the root of the project directory.
    // Ideally, the following would work:
    //
    // Path pathToZip = Paths.get(zipFile.getAbsolutePath());
    // FileSystem fs = FileSystems.newFileSystem(pathToZip, /* loader */ null);
    // Path root = Iterables.getOnlyElement(fs.getRootDirectories());
    // MoreFiles.copyRecursively(root, projectRoot);
    //
    // Unfortunately, this does not appear to work, in practice, because MoreFiles fails when trying
    // to resolve a Path for a zip entry against a file Path on disk.

    // TODO(user, simons): Make this work on Windows. A custom implementation of unzip in Java
    // needs to be heavily tested to ensure that it works on all platforms in a multithreaded
    // environment. In my testing of the unzip executable, this has not been an issue, so this level
    // of fidelity needs to be maintained.
    ProcessBuilder processBuilder = new ProcessBuilder(
        "unzip", "-o", "-qq", zipFile.getAbsolutePath());
    processBuilder.directory(projectRoot.toFile());

    // TODO(mbolin): In the failure cases, try to clean up or warn the user?
    try {
      Process process = processBuilder.start();
      int exitCode = process.waitFor();
      if (exitCode != 0) {
        throw new RuntimeException("Failed to unzip " + zipFile);
      }
    } catch (IOException | InterruptedException e) {
      return false;
    }

    // We only delete the ZIP file when it has been unzipped successfully. Otherwise, we leave it
    // around for debugging purposes.
    zipFile.delete();
    return true;
  }

  /**
   * Execute the commands for this build rule. Requires all dependent rules are already built
   * successfully.
   */
  private void executeCommandsNowThatDepsAreBuilt(BuildContext context,
      OnDiskBuildInfo onDiskBuildInfo,
      BuildInfoRecorder buildInfoRecorder)
      throws IOException, StepFailedException {
    context.logBuildInfo("[BUILDING %s]", getFullyQualifiedName());

    // Get and run all of the commands.
    BuildableContext buildableContext = new DefaultBuildableContext(onDiskBuildInfo,
        buildInfoRecorder);
    List<Step> steps = buildable.getBuildSteps(context, buildableContext);
    StepRunner stepRunner = context.getStepRunner();
    for (Step step : steps) {
      stepRunner.runStepForBuildTarget(step, getBuildTarget());
    }
  }

  /**
   * For a rule that is read from the build cache, it may have fields that would normally be
   * populated by executing the steps returned by
   * {@link Buildable#getBuildSteps(BuildContext, BuildableContext)}. Because
   * {@link Buildable#getBuildSteps(BuildContext, BuildableContext)} is not invoked for cached rules, a rule
   * may need to implement this method to populate those fields in some other way. For a cached
   * rule, this method will be invoked just before the future returned by
   * {@link #build(BuildContext)} is resolved.
   * @param onDiskBuildInfo can be used to read metadata from disk to help initialize the rule.
   */
  protected void initializeFromDisk(OnDiskBuildInfo onDiskBuildInfo) {}

  /**
   * This is a union type that represents either a success or a failure. This exists so that
   * {@link #buildOnceDepsAreBuilt(BuildContext, OnDiskBuildInfo, BuildInfoRecorder)} can return a
   * strongly typed value.
   */
  private static class BuildResult {

    private final BuildRuleStatus status;
    private final CacheResult cacheResult;

    @Nullable private final BuildRuleSuccess.Type success;
    @Nullable private final Throwable failure;

    BuildResult(BuildRuleSuccess.Type success, CacheResult cacheResult) {
      this.status = BuildRuleStatus.SUCCESS;
      this.cacheResult = Preconditions.checkNotNull(cacheResult);
      this.success = Preconditions.checkNotNull(success);
      this.failure = null;
    }

    BuildResult(Throwable failure) {
      this.status = BuildRuleStatus.FAIL;
      this.cacheResult = CacheResult.MISS;
      this.success = null;
      this.failure = Preconditions.checkNotNull(failure);
    }

    boolean isSuccess() {
      return status == BuildRuleStatus.SUCCESS;
    }
  }

  /**
   * Helper function for subclasses to create their lists of files for caching.
   */
  protected static void addInputsToSortedSet(@Nullable String pathToDirectory,
      ImmutableSortedSet.Builder<String> inputsToConsiderForCachingPurposes,
      DirectoryTraverser traverser) {
    if (pathToDirectory == null) {
      return;
    }
    Set<String> files = DirectoryTraversers.getInstance().findFiles(
        ImmutableSet.of(pathToDirectory), traverser);
    inputsToConsiderForCachingPurposes.addAll(files);
  }
}
