// 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) {
    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 path and
    // then go up the parent hierarchy.
    Path ownerConfigFolder = absolutePath;

    // 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);
    }
  }
}
