// 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, 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 {

  private static final SkyKeyInterner<RootedPath> interner = SkyKey.newInterner();

  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);
    return interner.intern(new RootedPath(root, rootRelativePath));
  }

  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
  public SkyKeyInterner<?> getSkyKeyInterner() {
    return interner;
  }
}
