// 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.vfs;

import static com.google.common.base.Preconditions.checkArgument;

import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.skyframe.SkyKey;
import java.util.Comparator;
import javax.annotation.Nullable;

/**
 * A {@link PathFragment} relative to a {@link Root}. Typically, the root is a package path entry.
 *
 * <p>Two {@link RootedPath}s are considered equal iff they have equal roots and equal relative
 * paths.
 *
 * <p>Instances are interned (except on Windows), which results in a large memory benefit (see
 * cl/516855266). In addition to being a {@link SkyKey} itself, {@link RootedPath} is used as a
 * field in several other common {@link SkyKey} types. Interning on the level of those keys does not
 * deduplicate referenced {@link RootedPath} instances which are also used as a {@link SkyKey}
 * directly.
 */
@AutoCodec
public final class RootedPath implements Comparable<RootedPath>, FileStateKey {

  // Interning on Windows (case-insensitive) surfaces a bug where paths that only differ in casing
  // use the same RootedPath instance.
  // TODO(#17904): Investigate this bug and add test coverage.
  @Nullable
  private static final SkyKeyInterner<RootedPath> interner =
      OsPathPolicy.getFilePathOs().isCaseSensitive() ? SkyKey.newInterner() : null;

  private final Root root;
  private final PathFragment rootRelativePath;

  // Cache the hash code: RootedPath is used in several of the most common SkyKeys, and we have a
  // free field to spend on it.
  private final transient int hashCode;

  /** Constructs a {@link RootedPath} from a {@link Root} and path fragment relative to the root. */
  @AutoCodec.Instantiator
  @AutoCodec.VisibleForSerialization
  static RootedPath createInternal(Root root, PathFragment rootRelativePath) {
    checkArgument(
        rootRelativePath.isAbsolute() == root.isAbsolute(),
        "rootRelativePath: %s root: %s",
        rootRelativePath,
        root);
    var rootedPath = new RootedPath(root, rootRelativePath);
    return interner != null ? interner.intern(rootedPath) : rootedPath;
  }

  private RootedPath(Root root, PathFragment rootRelativePath) {
    this.root = root;
    this.rootRelativePath = rootRelativePath;
    this.hashCode = 31 * root.hashCode() + rootRelativePath.hashCode();
  }

  /** Returns a rooted path representing {@code rootRelativePath} relative to {@code root}. */
  public static RootedPath toRootedPath(Root root, PathFragment rootRelativePath) {
    if (rootRelativePath.isAbsolute() && !root.isAbsolute()) {
      checkArgument(
          root.contains(rootRelativePath),
          "rootRelativePath '%s' is absolute, but it's not under root '%s'",
          rootRelativePath,
          root);
      rootRelativePath = root.relativize(rootRelativePath);
    }
    return createInternal(root, rootRelativePath);
  }

  /** Returns a rooted path representing {@code path} under the root {@code root}. */
  public static RootedPath toRootedPath(Root root, Path path) {
    checkArgument(root.contains(path), "path: %s root: %s", path, root);
    return toRootedPath(root, path.asFragment());
  }

  /**
   * Returns a rooted path representing {@code path} under one of the specified roots, or under the
   * file system root if it's not under any of the roots in {@code packagePathRoots}.
   */
  public static RootedPath toRootedPathMaybeUnderRoot(Path path, Iterable<Root> packagePathRoots) {
    for (Root root : packagePathRoots) {
      if (root.contains(path)) {
        return toRootedPath(root, path);
      }
    }
    return toRootedPath(Root.absoluteRoot(path.getFileSystem()), path);
  }

  public Path asPath() {
    return root.getRelative(rootRelativePath);
  }

  public Root getRoot() {
    return root;
  }

  /** Returns the path fragment relative to {@code #getRoot}. */
  public PathFragment getRootRelativePath() {
    return rootRelativePath;
  }

  @Nullable
  public RootedPath getParentDirectory() {
    PathFragment rootRelativeParentDirectory = rootRelativePath.getParentDirectory();
    if (rootRelativeParentDirectory == null) {
      return null;
    }
    return createInternal(root, rootRelativeParentDirectory);
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (!(obj instanceof RootedPath)) {
      return false;
    }
    RootedPath other = (RootedPath) obj;
    return hashCode == other.hashCode
        && root.equals(other.root)
        && rootRelativePath.equals(other.rootRelativePath);
  }

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

  @Override
  public String toString() {
    return "[" + root + "]/[" + rootRelativePath + "]";
  }

  @Override
  public int compareTo(RootedPath o) {
    return COMPARATOR.compare(this, o);
  }

  private static final Comparator<RootedPath> COMPARATOR =
      Comparator.comparing(RootedPath::getRoot).thenComparing(RootedPath::getRootRelativePath);

  @Override
  public RootedPath argument() {
    return this;
  }

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