// Copyright 2016 The Bazel Authors. All rights reserved.
//
// 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.google.devtools.build.lib.skyframe;

import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.lib.skyframe.serialization.VisibleForSerialization;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.SerializationConstant;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.RootedPath;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import java.util.Objects;
import javax.annotation.Nullable;

/**
 * The value computed by {@link CollectPackagesUnderDirectoryFunction}. Contains a mapping for all
 * its non-excluded directories to whether there are packages or error messages beneath them.
 *
 * <p>This value is used by {@link
 * com.google.devtools.build.lib.pkgcache.RecursivePackageProvider#streamPackagesUnderDirectory} to
 * help it traverse the graph and find the set of packages under a directory, recursively by {@link
 * CollectPackagesUnderDirectoryFunction} which computes a value for a directory by aggregating
 * results calculated from its subdirectories, and by {@link
 * PrepareDepsOfTargetsUnderDirectoryFunction} which uses this value to find transitive targets to
 * load.
 *
 * <p>Note that even though the {@link CollectPackagesUnderDirectoryFunction} is evaluated in part
 * because of its side-effects (i.e. loading transitive dependencies of targets), this value
 * interacts safely with change pruning, despite the fact that this value is a lossy representation
 * of the packages beneath a directory (i.e. it doesn't care <b>which</b> packages are under a
 * directory, just whether there are any). When the targets in a package change, the {@link
 * PackageValue} that {@link CollectPackagesUnderDirectoryFunction} depends on will be invalidated,
 * and the PrepareDeps function for that package's directory will be reevaluated, loading any new
 * transitive dependencies. Change pruning may prevent the reevaluation of PrepareDeps for
 * directories above that one, but they don't need to be re-run.
 */
public abstract class CollectPackagesUnderDirectoryValue implements SkyValue {
  @VisibleForSerialization
  protected final ImmutableMap<RootedPath, Boolean>
      subdirectoryTransitivelyContainsPackagesOrErrors;

  CollectPackagesUnderDirectoryValue(
      ImmutableMap<RootedPath, Boolean> subdirectoryTransitivelyContainsPackagesOrErrors) {
    this.subdirectoryTransitivelyContainsPackagesOrErrors =
        Preconditions.checkNotNull(subdirectoryTransitivelyContainsPackagesOrErrors);
  }

  /** Represents a successfully loaded package or a directory without a BUILD file. */
  public static class NoErrorCollectPackagesUnderDirectoryValue
      extends CollectPackagesUnderDirectoryValue {
    @SerializationConstant
    public static final NoErrorCollectPackagesUnderDirectoryValue EMPTY =
        new NoErrorCollectPackagesUnderDirectoryValue(
            false, ImmutableMap.<RootedPath, Boolean>of());

    private final boolean isDirectoryPackage;

    private NoErrorCollectPackagesUnderDirectoryValue(
        boolean isDirectoryPackage,
        ImmutableMap<RootedPath, Boolean> subdirectoryTransitivelyContainsPackagesOrErrors) {
      super(subdirectoryTransitivelyContainsPackagesOrErrors);
      this.isDirectoryPackage = isDirectoryPackage;
    }

    @Override
    public boolean isDirectoryPackage() {
      return isDirectoryPackage;
    }

    @Nullable
    @Override
    public String getErrorMessage() {
      return null;
    }

    @Override
    public int hashCode() {
      return Objects.hash(
          isDirectoryPackage, getSubdirectoryTransitivelyContainsPackagesOrErrors());
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (!(o instanceof NoErrorCollectPackagesUnderDirectoryValue)) {
        return false;
      }
      NoErrorCollectPackagesUnderDirectoryValue that =
          (NoErrorCollectPackagesUnderDirectoryValue) o;
      return this.isDirectoryPackage == that.isDirectoryPackage
          && Objects.equals(
              this.getSubdirectoryTransitivelyContainsPackagesOrErrors(),
              that.getSubdirectoryTransitivelyContainsPackagesOrErrors());
    }

    @Override
    public String toString() {
      return MoreObjects.toStringHelper(this)
          .add("isDirectoryPackage", isDirectoryPackage)
          .add(
              "subdirectoryTransitivelyContainsPackagesOrErrors",
              getSubdirectoryTransitivelyContainsPackagesOrErrors())
          .toString();
    }

  }

  /** Represents a directory with a BUILD file that failed to load. */
  private static class ErrorCollectPackagesUnderDirectoryValue
      extends CollectPackagesUnderDirectoryValue {
    private final String errorMessage;

    ErrorCollectPackagesUnderDirectoryValue(
        String errorMessage,
        ImmutableMap<RootedPath, Boolean> subdirectoryTransitivelyContainsPackagesOrErrors) {
      super(subdirectoryTransitivelyContainsPackagesOrErrors);
      this.errorMessage = Preconditions.checkNotNull(errorMessage);
    }

    @Override
    public boolean isDirectoryPackage() {
      return false;
    }

    @Override
    public String getErrorMessage() {
      return errorMessage;
    }

    @Override
    public int hashCode() {
      return Objects.hash(errorMessage, getSubdirectoryTransitivelyContainsPackagesOrErrors());
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (!(o instanceof ErrorCollectPackagesUnderDirectoryValue)) {
        return false;
      }
      ErrorCollectPackagesUnderDirectoryValue that = (ErrorCollectPackagesUnderDirectoryValue) o;
      return Objects.equals(this.errorMessage, that.errorMessage)
          && Objects.equals(
              this.getSubdirectoryTransitivelyContainsPackagesOrErrors(),
              that.getSubdirectoryTransitivelyContainsPackagesOrErrors());
    }

    @Override
    public String toString() {
      return MoreObjects.toStringHelper(this)
          .add("errorMessage", errorMessage)
          .add(
              "subdirectoryTransitivelyContainsPackagesOrErrors",
              getSubdirectoryTransitivelyContainsPackagesOrErrors())
          .toString();
    }
  }

  /**
   * Constructs a {@link CollectPackagesUnderDirectoryValue} for a directory with a BUILD file that
   * failed to load as a package.
   */
  public static CollectPackagesUnderDirectoryValue ofError(
      String errorMessage,
      ImmutableMap<RootedPath, Boolean> subdirectoryTransitivelyContainsPackagesOrErrors) {
    Preconditions.checkNotNull(errorMessage, "errorMessage");
    return new ErrorCollectPackagesUnderDirectoryValue(
        errorMessage, subdirectoryTransitivelyContainsPackagesOrErrors);
  }

  /**
   * Constructs a {@link CollectPackagesUnderDirectoryValue} for a directory without a BUILD file or
   * that has a BUILD file that successfully loads as a package.
   */
  public static CollectPackagesUnderDirectoryValue ofNoError(
      boolean isDirectoryPackage,
      ImmutableMap<RootedPath, Boolean> subdirectoryTransitivelyContainsPackagesOrErrors) {
    if (!isDirectoryPackage && subdirectoryTransitivelyContainsPackagesOrErrors.isEmpty()) {
      return NoErrorCollectPackagesUnderDirectoryValue.EMPTY;
    }
    return new NoErrorCollectPackagesUnderDirectoryValue(
        isDirectoryPackage, subdirectoryTransitivelyContainsPackagesOrErrors);
  }

  /**
   * Returns whether there is a BUILD file in this directory that can be loaded as a package. If
   * this returns {@code true}, then {@link #getErrorMessage()} returns {@code null}.
   */
  public abstract boolean isDirectoryPackage();

  /**
   * Returns an error describing why the BUILD file in this directory cannot be loaded as a package,
   * if there is one and it can't be. Otherwise returns {@code null}. If this returns non-{@code
   * null}, then {@link #isDirectoryPackage()} returns {@code false}.
   */
  @Nullable
  public abstract String getErrorMessage();

  /**
   * Returns an {@link ImmutableMap} describing each immediate subdirectory of this directory and
   * whether there are any packages, or BUILD files that couldn't be loaded, in or beneath that
   * subdirectory.
   */
  public final ImmutableMap<RootedPath, Boolean>
      getSubdirectoryTransitivelyContainsPackagesOrErrors() {
    return subdirectoryTransitivelyContainsPackagesOrErrors;
  }

  /** Create a collect packages under directory request. */
  @ThreadSafe
  public static SkyKey key(
      RepositoryName repository, RootedPath rootedPath, ImmutableSet<PathFragment> excludedPaths) {
    return Key.create(repository, rootedPath, excludedPaths);
  }

  @VisibleForSerialization
  @AutoCodec
  static class Key extends RecursivePkgSkyKey {
    private static final SkyKeyInterner<Key> interner = SkyKey.newInterner();

    private Key(
        RepositoryName repositoryName,
        RootedPath rootedPath,
        ImmutableSet<PathFragment> excludedPaths) {
      super(repositoryName, rootedPath, excludedPaths);
    }

    @VisibleForSerialization
    @AutoCodec.Instantiator
    static Key create(
        RepositoryName repositoryName,
        RootedPath rootedPath,
        ImmutableSet<PathFragment> excludedPaths) {
      return interner.intern(new Key(repositoryName, rootedPath, excludedPaths));
    }

    @Override
    public SkyFunctionName functionName() {
      return SkyFunctions.COLLECT_PACKAGES_UNDER_DIRECTORY;
    }

    @Override
    public SkyKeyInterner<Key> getSkyKeyInterner() {
      return interner;
    }
  }
}
