// Copyright (C) 2020 The Android Open Source Project
//
// 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.gerrit.plugins.codeowners.backend;

import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;

import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.inject.Inject;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
import java.util.function.Consumer;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;

/**
 * Class to visit the code owner configs in a given branch that apply for a given path by following
 * the path hierarchy from the given path up to the root folder and the default code owner config in
 * {@code refs/meta/config}.
 *
 * <p>The default code owner config in {@code refs/meta/config} is the parent of the code owner
 * config in the root folder of the branch. The same as any other parent it can be ignored (e.g. by
 * using {@code set noparent} in the root code owner config if the {@code find-owners} backend is
 * used).
 */
public class CodeOwnerConfigHierarchy {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final GitRepositoryManager repoManager;
  private final PathCodeOwners.Factory pathCodeOwnersFactory;
  private final TransientCodeOwnerConfigCache transientCodeOwnerConfigCache;

  @Inject
  CodeOwnerConfigHierarchy(
      GitRepositoryManager repoManager,
      PathCodeOwners.Factory pathCodeOwnersFactory,
      TransientCodeOwnerConfigCache transientCodeOwnerConfigCache) {
    this.repoManager = repoManager;
    this.pathCodeOwnersFactory = pathCodeOwnersFactory;
    this.transientCodeOwnerConfigCache = transientCodeOwnerConfigCache;
  }

  /**
   * Visits the code owner configs in the given branch that apply for the given path by following
   * the path hierarchy from the given path up to the root folder.
   *
   * @param branchNameKey project and branch from which the code owner configs should be visited
   * @param revision the branch revision from which the code owner configs should be loaded
   * @param absolutePath the path for which the code owner configs should be visited; the path must
   *     be absolute; can be the path of a file or folder; the path may or may not exist
   * @param codeOwnerConfigVisitor visitor that should be invoked for the applying code owner
   *     configs
   */
  public void visit(
      BranchNameKey branchNameKey,
      ObjectId revision,
      Path absolutePath,
      CodeOwnerConfigVisitor codeOwnerConfigVisitor) {
    visit(
        branchNameKey,
        revision,
        absolutePath,
        codeOwnerConfigVisitor,
        /* parentCodeOwnersIgnoredCallback= */ codeOwnerConfigKey -> {});
  }

  /**
   * Visits the code owner configs in the given branch that apply for the given path by following
   * the path hierarchy from the given path up to the root folder.
   *
   * @param branchNameKey project and branch from which the code owner configs should be visited
   * @param revision the branch revision from which the code owner configs should be loaded
   * @param absolutePath the path for which the code owner configs should be visited; the path must
   *     be absolute; can be the path of a file or folder; the path may or may not exist
   * @param codeOwnerConfigVisitor visitor that should be invoked for the applying code owner
   *     configs
   * @param parentCodeOwnersIgnoredCallback callback that is invoked for the first visited code
   *     owner config that ignores parent code owners
   */
  public void visit(
      BranchNameKey branchNameKey,
      ObjectId revision,
      Path absolutePath,
      CodeOwnerConfigVisitor codeOwnerConfigVisitor,
      Consumer<CodeOwnerConfig.Key> parentCodeOwnersIgnoredCallback) {
    requireNonNull(codeOwnerConfigVisitor, "codeOwnerConfigVisitor");
    PathCodeOwnersVisitor pathCodeOwnersVisitor =
        pathCodeOwners -> codeOwnerConfigVisitor.visit(pathCodeOwners.getCodeOwnerConfig());
    visit(
        branchNameKey,
        revision,
        absolutePath,
        pathCodeOwnersVisitor,
        parentCodeOwnersIgnoredCallback);
  }

  /**
   * Visits the path code owners in the given branch that apply for the given path by following the
   * path hierarchy from the given path up to the root folder.
   *
   * @param branchNameKey project and branch from which the code owner configs should be visited
   * @param revision the branch revision from which the code owner configs should be loaded
   * @param absolutePath the path for which the code owner configs should be visited; the path must
   *     be absolute; can be the path of a file or folder; the path may or may not exist
   * @param pathCodeOwnersVisitor visitor that should be invoked for the applying path code owners
   * @param parentCodeOwnersIgnoredCallback callback that is invoked for the first visited code
   *     owner config that ignores parent code owners
   */
  public void visit(
      BranchNameKey branchNameKey,
      ObjectId revision,
      Path absolutePath,
      PathCodeOwnersVisitor pathCodeOwnersVisitor,
      Consumer<CodeOwnerConfig.Key> parentCodeOwnersIgnoredCallback) {
    visit(
        branchNameKey,
        revision,
        absolutePath,
        absolutePath,
        pathCodeOwnersVisitor,
        parentCodeOwnersIgnoredCallback);
  }

  /**
   * Visits the path code owners in the given branch that apply for the given file path by following
   * the path hierarchy from the given path up to the root folder.
   *
   * <p>Same as {@link #visit(BranchNameKey, ObjectId, Path, PathCodeOwnersVisitor, Consumer)} with
   * the only difference that the provided path must be a file path (no folder path). Knowing that
   * that the path is a file path allows us to skip checking if there is a code owner config file in
   * this path (if it's a file it cannot contain a code owner config file). This is a performance
   * optimization that matters if code owner config files need to be looked up for 1000s of files
   * (e.g. for large changes).
   *
   * @param branchNameKey project and branch from which the code owner configs should be visited
   * @param revision the branch revision from which the code owner configs should be loaded
   * @param absoluteFilePath the path for which the code owner configs should be visited; the path
   *     must be absolute; must be the path of a file; the path may or may not exist
   * @param pathCodeOwnersVisitor visitor that should be invoked for the applying path code owners
   * @param parentCodeOwnersIgnoredCallback callback that is invoked for the first visited code
   *     owner config that ignores parent code owners
   */
  public void visitForFile(
      BranchNameKey branchNameKey,
      ObjectId revision,
      Path absoluteFilePath,
      PathCodeOwnersVisitor pathCodeOwnersVisitor,
      Consumer<CodeOwnerConfig.Key> parentCodeOwnersIgnoredCallback) {
    visit(
        branchNameKey,
        revision,
        absoluteFilePath,
        absoluteFilePath.getParent(),
        pathCodeOwnersVisitor,
        parentCodeOwnersIgnoredCallback);
  }

  private void visit(
      BranchNameKey branchNameKey,
      ObjectId revision,
      Path absolutePath,
      Path startFolder,
      PathCodeOwnersVisitor pathCodeOwnersVisitor,
      Consumer<CodeOwnerConfig.Key> parentCodeOwnersIgnoredCallback) {
    requireNonNull(branchNameKey, "branch");
    requireNonNull(revision, "revision");
    requireNonNull(absolutePath, "absolutePath");
    requireNonNull(pathCodeOwnersVisitor, "pathCodeOwnersVisitor");
    requireNonNull(parentCodeOwnersIgnoredCallback, "parentCodeOwnersIgnoredCallback");
    checkState(absolutePath.isAbsolute(), "path %s must be absolute", absolutePath);

    logger.atFine().log(
        "visiting code owner configs for '%s' in branch '%s' in project '%s' (revision = '%s')",
        absolutePath, branchNameKey.shortName(), branchNameKey.project(), revision.name());

    // Next path in which we look for a code owner configuration. We start at the given folder and
    // then go up the parent hierarchy.
    Path ownerConfigFolder = startFolder;

    // Iterate over the parent code owner configurations.
    while (ownerConfigFolder != null) {
      // Read code owner config and invoke the codeOwnerConfigVisitor if the code owner config
      // exists.
      logger.atFine().log("inspecting code owner config for %s", ownerConfigFolder);
      CodeOwnerConfig.Key codeOwnerConfigKey =
          CodeOwnerConfig.Key.create(branchNameKey, ownerConfigFolder);
      Optional<PathCodeOwners> pathCodeOwners =
          pathCodeOwnersFactory.create(
              transientCodeOwnerConfigCache, codeOwnerConfigKey, revision, absolutePath);
      if (pathCodeOwners.isPresent()) {
        logger.atFine().log("visit code owner config for %s", ownerConfigFolder);
        boolean visitFurtherCodeOwnerConfigs = pathCodeOwnersVisitor.visit(pathCodeOwners.get());
        boolean ignoreParentCodeOwners =
            pathCodeOwners.get().resolveCodeOwnerConfig().get().ignoreParentCodeOwners();
        if (ignoreParentCodeOwners) {
          parentCodeOwnersIgnoredCallback.accept(codeOwnerConfigKey);
        }
        logger.atFine().log(
            "visitFurtherCodeOwnerConfigs = %s, ignoreParentCodeOwners = %s",
            visitFurtherCodeOwnerConfigs, ignoreParentCodeOwners);
        if (!visitFurtherCodeOwnerConfigs || ignoreParentCodeOwners) {
          // If no further code owner configs should be visited or if all parent code owner configs
          // are ignored, we are done.
          // No need to check further parent code owner configs (including the default code owner
          // config in refs/meta/config which is the parent of the root code owner config), hence we
          // can return here.
          return;
        }
      } else {
        logger.atFine().log("no code owner config found in %s", ownerConfigFolder);
      }

      // Continue the loop with the next parent folder.
      ownerConfigFolder = ownerConfigFolder.getParent();
    }

    if (!RefNames.REFS_CONFIG.equals(branchNameKey.branch())) {
      visitCodeOwnerConfigInRefsMetaConfig(
          branchNameKey.project(), absolutePath, pathCodeOwnersVisitor);
    }
  }

  /**
   * Visits the code owner config file at the root of the {@code refs/meta/config} branch in the
   * given project.
   *
   * <p>The root code owner config file in the {@code refs/meta/config} branch defines default code
   * owners for all branches.
   *
   * <p>There is no inheritance of code owner config files from parent projects. If code owners
   * should be defined for child projects, this is possible via global code owners, but not via the
   * default code owner config file in {@code refs/meta/config}.
   *
   * @param project the project in which we want to visit the code owner config file at the root of
   *     the {@code refs/meta/config} branch
   * @param absolutePath the path for which the code owner configs should be visited; the path must
   *     be absolute; can be the path of a file or folder; the path may or may not exist
   * @param pathCodeOwnersVisitor visitor that should be invoked
   */
  private void visitCodeOwnerConfigInRefsMetaConfig(
      Project.NameKey project, Path absolutePath, PathCodeOwnersVisitor pathCodeOwnersVisitor) {
    CodeOwnerConfig.Key metaCodeOwnerConfigKey =
        CodeOwnerConfig.Key.create(project, RefNames.REFS_CONFIG, "/");
    logger.atFine().log("visiting code owner config %s", metaCodeOwnerConfigKey);
    try (Repository repository = repoManager.openRepository(project);
        RevWalk rw = new RevWalk(repository)) {
      Ref ref = repository.exactRef(RefNames.REFS_CONFIG);
      if (ref == null) {
        logger.atFine().log("%s not found", RefNames.REFS_CONFIG);
        return;
      }
      RevCommit metaRevision = rw.parseCommit(ref.getObjectId());
      Optional<PathCodeOwners> pathCodeOwners =
          pathCodeOwnersFactory.create(
              transientCodeOwnerConfigCache, metaCodeOwnerConfigKey, metaRevision, absolutePath);
      if (pathCodeOwners.isPresent()) {
        logger.atFine().log("visit code owner config %s", metaCodeOwnerConfigKey);
        pathCodeOwnersVisitor.visit(pathCodeOwners.get());
      } else {
        logger.atFine().log("code owner config %s not found", metaCodeOwnerConfigKey);
      }
    } catch (IOException e) {
      throw new CodeOwnersInternalServerErrorException(
          String.format("failed to read %s", metaCodeOwnerConfigKey), e);
    }
  }

  /** Returns the counters for cache and backend reads of code owner config files. */
  public TransientCodeOwnerConfigCache.Counters getCodeOwnerConfigCounters() {
    return transientCodeOwnerConfigCache.getCounters();
  }
}
