// Copyright 2014 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.Objects;
import com.google.common.base.Preconditions;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.packages.BuildFileName;
import com.google.devtools.build.lib.rules.repository.RepositoryDirectoryValue;
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.Root;
import com.google.devtools.build.lib.vfs.RootedPath;
import com.google.devtools.build.skyframe.AbstractSkyKey;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import java.util.function.Predicate;
import javax.annotation.Nullable;

/**
 * A value that represents a package lookup result.
 *
 * <p>Package lookups will always produce a value. On success, the {@code #getRoot} returns the
 * package path root under which the package resides and the package's BUILD file is guaranteed to
 * exist (unless this is looking up a WORKSPACE file, in which case the underlying file may or may
 * not exist. On failure, {@code #getErrorReason} and {@code #getErrorMsg} describe why the package
 * doesn't exist.
 *
 * <p>Implementation detail: we use inheritance here to optimize for memory usage.
 */
public abstract class PackageLookupValue implements SkyValue {

  @SerializationConstant
  public static final NoBuildFilePackageLookupValue NO_BUILD_FILE_VALUE =
      new NoBuildFilePackageLookupValue();

  @SerializationConstant
  public static final DeletedPackageLookupValue DELETED_PACKAGE_VALUE =
      new DeletedPackageLookupValue();

  enum ErrorReason {
    /** There is no BUILD file. */
    NO_BUILD_FILE,

    /** The package name is invalid. */
    INVALID_PACKAGE_NAME,

    /** The package is considered deleted because of --deleted_packages. */
    DELETED_PACKAGE,

    /** The repository was not found. */
    REPOSITORY_NOT_FOUND
  }

  protected PackageLookupValue() {}

  public static PackageLookupValue success(
      RepositoryDirectoryValue repository, Root root, BuildFileName buildFileName) {
    return new SuccessfulPackageLookupValue(repository, root, buildFileName);
  }

  public static PackageLookupValue success(Root root, BuildFileName buildFileName) {
    return new SuccessfulPackageLookupValue(null, root, buildFileName);
  }

  public static PackageLookupValue invalidPackageName(String errorMsg) {
    return new InvalidNamePackageLookupValue(errorMsg);
  }

  public static PackageLookupValue incorrectRepositoryReference(
      PackageIdentifier invalidPackage, PackageIdentifier correctPackage) {
    return new IncorrectRepositoryReferencePackageLookupValue(invalidPackage, correctPackage);
  }

  /**
   * For a successful package lookup, returns the root (package path entry) that the package resides
   * in.
   */
  public abstract Root getRoot();

  /** For a successful package lookup, returns the build file name that the package uses. */
  public abstract BuildFileName getBuildFileName();

  /** Returns whether the package lookup was successful. */
  public abstract boolean packageExists();

  /**
   * For a successful package lookup, returns the {@link RootedPath} for the build file that defines
   * the package.
   */
  public RootedPath getRootedPath(PackageIdentifier packageIdentifier) {
    return RootedPath.toRootedPath(
        getRoot(), getBuildFileName().getBuildFileFragment(packageIdentifier));
  }

  /**
   * For an unsuccessful package lookup, gets the reason why {@link #packageExists} returns {@code
   * false}.
   */
  abstract ErrorReason getErrorReason();

  /**
   * For an unsuccessful package lookup, gets a detailed error message for {@link #getErrorReason}
   * that is suitable for reporting to a user.
   */
  public abstract String getErrorMsg();

  public static SkyKey key(PathFragment directory) {
    Preconditions.checkArgument(!directory.isAbsolute(), directory);
    return key(PackageIdentifier.createInMainRepo(directory));
  }

  public static Key key(PackageIdentifier pkgIdentifier) {
    return Key.create(pkgIdentifier);
  }

  static boolean appliesToKey(SkyKey key, Predicate<PackageIdentifier> identifierPredicate) {
    return SkyFunctions.PACKAGE_LOOKUP.equals(key.functionName())
        && identifierPredicate.test((PackageIdentifier) key.argument());
  }

  /** {@link SkyKey} for {@link PackageLookupValue} computation. */
  @VisibleForSerialization
  @AutoCodec
  static class Key extends AbstractSkyKey<PackageIdentifier> {
    private static final SkyKeyInterner<Key> interner = SkyKey.newInterner();

    private Key(PackageIdentifier arg) {
      super(arg);
    }

    private static Key create(PackageIdentifier arg) {
      return interner.intern(new Key(arg));
    }

    @VisibleForSerialization
    @AutoCodec.Interner
    static Key intern(Key key) {
      return interner.intern(key);
    }

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

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

  /** Successful lookup value. */
  public static class SuccessfulPackageLookupValue extends PackageLookupValue {
    /**
     * The repository value the meaning of the path depends on (e.g., an external repository
     * controlling a symbolic link the path goes trough). Can be {@code null}, if does not depend on
     * such a repository; will always be {@code null} for packages in the main repository.
     */
    @Nullable private final RepositoryDirectoryValue repository;

    private final Root root;
    private final BuildFileName buildFileName;

    SuccessfulPackageLookupValue(
        @Nullable RepositoryDirectoryValue repository, Root root, BuildFileName buildFileName) {
      this.repository = repository;
      this.root = root;
      this.buildFileName = buildFileName;
    }

    @Nullable
    public RepositoryDirectoryValue repository() {
      return repository;
    }

    @Override
    public boolean packageExists() {
      return true;
    }

    @Override
    public Root getRoot() {
      return root;
    }

    @Override
    public BuildFileName getBuildFileName() {
      return buildFileName;
    }

    @Override
    ErrorReason getErrorReason() {
      throw new IllegalStateException();
    }

    @Override
    public String getErrorMsg() {
      throw new IllegalStateException();
    }

    @Override
    public boolean equals(Object obj) {
      if (!(obj instanceof SuccessfulPackageLookupValue)) {
        return false;
      }
      SuccessfulPackageLookupValue other = (SuccessfulPackageLookupValue) obj;
      return root.equals(other.root)
          && buildFileName == other.buildFileName
          && Objects.equal(repository, other.repository);
    }

    @Override
    public int hashCode() {
      return Objects.hashCode(root.hashCode(), buildFileName.hashCode(), repository);
    }
  }

  private abstract static class UnsuccessfulPackageLookupValue extends PackageLookupValue {

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

    @Override
    public Root getRoot() {
      throw new IllegalStateException();
    }

    @Override
    public BuildFileName getBuildFileName() {
      throw new IllegalStateException();
    }
  }

  /** Marker value for no build file found. */
  public static class NoBuildFilePackageLookupValue extends UnsuccessfulPackageLookupValue {

    private NoBuildFilePackageLookupValue() {}

    @Override
    ErrorReason getErrorReason() {
      return ErrorReason.NO_BUILD_FILE;
    }

    @Override
    public String getErrorMsg() {
      return "BUILD file not found on package path";
    }
  }

  /** Value indicating the package name was in error. */
  public static class InvalidNamePackageLookupValue extends UnsuccessfulPackageLookupValue {

    private final String errorMsg;

    InvalidNamePackageLookupValue(String errorMsg) {
      this.errorMsg = errorMsg;
    }

    @Override
    ErrorReason getErrorReason() {
      return ErrorReason.INVALID_PACKAGE_NAME;
    }

    @Override
    public String getErrorMsg() {
      return errorMsg;
    }

    @Override
    public boolean equals(Object obj) {
      if (!(obj instanceof InvalidNamePackageLookupValue)) {
        return false;
      }
      InvalidNamePackageLookupValue other = (InvalidNamePackageLookupValue) obj;
      return errorMsg.equals(other.errorMsg);
    }

    @Override
    public int hashCode() {
      return errorMsg.hashCode();
    }

    @Override
    public String toString() {
      return String.format("%s: %s", this.getClass().getSimpleName(), this.errorMsg);
    }
  }

  /** Value indicating the package name was in error. */
  public static class IncorrectRepositoryReferencePackageLookupValue
      extends UnsuccessfulPackageLookupValue {

    private final PackageIdentifier invalidPackageIdentifier;
    private final PackageIdentifier correctedPackageIdentifier;

    IncorrectRepositoryReferencePackageLookupValue(
        PackageIdentifier invalidPackageIdentifier, PackageIdentifier correctedPackageIdentifier) {
      this.invalidPackageIdentifier = invalidPackageIdentifier;
      this.correctedPackageIdentifier = correctedPackageIdentifier;
    }

    PackageIdentifier getInvalidPackageIdentifier() {
      return invalidPackageIdentifier;
    }

    PackageIdentifier getCorrectedPackageIdentifier() {
      return correctedPackageIdentifier;
    }

    @Override
    ErrorReason getErrorReason() {
      return ErrorReason.INVALID_PACKAGE_NAME;
    }

    @Override
    public String getErrorMsg() {
      return String.format(
          "Invalid package reference %s crosses into repository %s:"
              + " did you mean to use %s instead?",
          invalidPackageIdentifier,
          correctedPackageIdentifier.getRepository(),
          correctedPackageIdentifier);
    }

    @Override
    public boolean equals(Object obj) {
      if (!(obj instanceof IncorrectRepositoryReferencePackageLookupValue)) {
        return false;
      }
      IncorrectRepositoryReferencePackageLookupValue other =
          (IncorrectRepositoryReferencePackageLookupValue) obj;
      return Objects.equal(invalidPackageIdentifier, other.invalidPackageIdentifier)
          && Objects.equal(correctedPackageIdentifier, other.correctedPackageIdentifier);
    }

    @Override
    public int hashCode() {
      return Objects.hashCode(invalidPackageIdentifier, correctedPackageIdentifier);
    }

    @Override
    public String toString() {
      return String.format(
          "%s: invalidPackageIdenfitier: %s, corrected: %s",
          this.getClass().getSimpleName(),
          this.invalidPackageIdentifier,
          this.correctedPackageIdentifier);
    }
  }

  /** Marker value for a deleted package. */
  public static class DeletedPackageLookupValue extends UnsuccessfulPackageLookupValue {
    private DeletedPackageLookupValue() {}

    @Override
    ErrorReason getErrorReason() {
      return ErrorReason.DELETED_PACKAGE;
    }

    @Override
    public String getErrorMsg() {
      return "Package is considered deleted due to --deleted_packages";
    }
  }

  /**
   * Value for repository we could not find. This can happen when looking for a label that specifies
   * a non-existent repository.
   */
  public static class NoRepositoryPackageLookupValue extends UnsuccessfulPackageLookupValue {
    private final RepositoryName repositoryName;
    private final String reason;

    NoRepositoryPackageLookupValue(RepositoryName repositoryName, String reason) {
      this.repositoryName = repositoryName;
      this.reason = reason;
    }

    @Override
    ErrorReason getErrorReason() {
      return ErrorReason.REPOSITORY_NOT_FOUND;
    }

    @Override
    public String getErrorMsg() {
      return String.format("The repository '%s' could not be resolved: %s", repositoryName, reason);
    }
  }

  /**
   * Creates the error message for the input {@linkplain Label label} has a subpackage crossing
   * boundary.
   *
   * <p>Returns {@code null} if no subpackage is discovered or the subpackage is marked as DELETED.
   */
  @Nullable
  static String getErrorMessageForLabelCrossingPackageBoundary(
      Root pkgRoot,
      Label label,
      PackageIdentifier subpackageIdentifier,
      PackageLookupValue packageLookupValue) {
    String message = null;
    if (packageLookupValue.packageExists()) {
      message =
          String.format(
              "Label '%s' is invalid because '%s' is a subpackage", label, subpackageIdentifier);
      Root subPackageRoot = packageLookupValue.getRoot();

      if (pkgRoot.equals(subPackageRoot)) {
        PathFragment labelRootPathFragment = label.getPackageIdentifier().getSourceRoot();
        PathFragment subpackagePathFragment = subpackageIdentifier.getSourceRoot();
        if (subpackagePathFragment.startsWith(labelRootPathFragment)) {
          PathFragment labelNameInSubpackage =
              PathFragment.create(label.getName())
                  .subFragment(
                      subpackagePathFragment.segmentCount() - labelRootPathFragment.segmentCount());
          message += "; perhaps you meant to put the" + " colon here: '";
          if (subpackageIdentifier.getRepository().isMain()) {
            message += "//";
          }
          message += subpackageIdentifier + ":" + labelNameInSubpackage + "'?";
        } else {
          // TODO: Is this a valid case? How do we handle this case?
        }
      } else {
        message +=
            "; have you deleted "
                + subpackageIdentifier
                + "/BUILD? "
                + "If so, use the --deleted_packages="
                + subpackageIdentifier
                + " option";
      }
    } else if (packageLookupValue instanceof IncorrectRepositoryReferencePackageLookupValue) {
      message =
          String.format(
              "Label '%s' is invalid because '%s' is a subpackage",
              label,
              ((IncorrectRepositoryReferencePackageLookupValue) packageLookupValue)
                  .correctedPackageIdentifier);
    }
    return message;
  }
}
