// 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.gerrit.plugins.codeowners.backend.CodeOwners.getInvalidCodeOwnerConfigCause;
import static java.util.Objects.requireNonNull;

import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginConfiguration;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.Optional;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevWalk;

/**
 * Class to scan a branch for code owner config files.
 *
 * <p>Whether the scan includes the code owner config file at the root of {@code refs/meta/config}
 * branch that contains the default code owners for the whole repository can be controlled via
 * {@link #includeDefaultCodeOwnerConfig(boolean)}.
 */
public class CodeOwnerConfigScanner {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public interface Factory {
    CodeOwnerConfigScanner create();
  }

  private final GitRepositoryManager repoManager;
  private final CodeOwnersPluginConfiguration codeOwnersPluginConfiguration;

  private boolean includeDefaultCodeOwnerConfig = true;

  @Inject
  CodeOwnerConfigScanner(
      GitRepositoryManager repoManager,
      CodeOwnersPluginConfiguration codeOwnersPluginConfiguration) {
    this.repoManager = repoManager;
    this.codeOwnersPluginConfiguration = codeOwnersPluginConfiguration;
  }

  /**
   * Whether the scan should include the code owner config file at the root of {@code
   * refs/meta/config} branch that contains the default code owners for the whole repository.
   */
  public CodeOwnerConfigScanner includeDefaultCodeOwnerConfig(
      boolean includeDefaultCodeOwnerConfig) {
    this.includeDefaultCodeOwnerConfig = includeDefaultCodeOwnerConfig;
    return this;
  }

  /**
   * Visits all code owner config files in the given project and branch.
   *
   * @param branchNameKey the project and branch for which the code owner config files should be
   *     visited
   * @param codeOwnerConfigVisitor the callback that is invoked for each code owner config file
   * @param invalidCodeOwnerConfigCallback callback that is invoked for invalid code owner config
   *     files
   */
  public void visit(
      BranchNameKey branchNameKey,
      CodeOwnerConfigVisitor codeOwnerConfigVisitor,
      InvalidCodeOwnerConfigCallback invalidCodeOwnerConfigCallback) {
    visit(
        branchNameKey,
        codeOwnerConfigVisitor,
        invalidCodeOwnerConfigCallback,
        /* pathGlob= */ null);
  }

  /**
   * Visits all code owner config files in the given project and branch.
   *
   * @param branchNameKey the project and branch for which the code owner config files should be
   *     visited
   * @param codeOwnerConfigVisitor the callback that is invoked for each code owner config file
   * @param invalidCodeOwnerConfigCallback callback that is invoked for invalid code owner config
   *     files
   * @param pathGlob optional Java NIO glob that the paths of code owner config files must match
   */
  public void visit(
      BranchNameKey branchNameKey,
      CodeOwnerConfigVisitor codeOwnerConfigVisitor,
      InvalidCodeOwnerConfigCallback invalidCodeOwnerConfigCallback,
      @Nullable String pathGlob) {
    requireNonNull(branchNameKey, "branchNameKey");
    requireNonNull(codeOwnerConfigVisitor, "codeOwnerConfigVisitor");
    requireNonNull(invalidCodeOwnerConfigCallback, "invalidCodeOwnerConfigCallback");

    CodeOwnerBackend codeOwnerBackend =
        codeOwnersPluginConfiguration
            .getProjectConfig(branchNameKey.project())
            .getBackend(branchNameKey.branch());
    logger.atFine().log(
        "scanning code owner files in branch %s of project %s (path glob = %s)",
        branchNameKey.branch(), branchNameKey.project(), pathGlob);

    if (includeDefaultCodeOwnerConfig && !RefNames.REFS_CONFIG.equals(branchNameKey.branch())) {
      logger.atFine().log("Scanning code owner config file in %s", RefNames.REFS_CONFIG);
      Optional<CodeOwnerConfig> metaCodeOwnerConfig =
          codeOwnerBackend.getCodeOwnerConfig(
              CodeOwnerConfig.Key.createWithFileName(
                  codeOwnerBackend, branchNameKey.project(), RefNames.REFS_CONFIG, "/"),
              /** revision */
              null);
      if (metaCodeOwnerConfig.isPresent()) {
        boolean visitFurtherCodeOwnerConfigFiles =
            codeOwnerConfigVisitor.visit(metaCodeOwnerConfig.get());
        if (!visitFurtherCodeOwnerConfigFiles) {
          // By returning false the callback told us to not visit any further code owner config
          // files, hence we are done and do not need to search for further code owner config files
          // in the branch.
          return;
        }
      }
    }

    try (Repository repository = repoManager.openRepository(branchNameKey.project());
        RevWalk rw = new RevWalk(repository);
        CodeOwnerConfigTreeWalk treeWalk =
            new CodeOwnerConfigTreeWalk(
                codeOwnerBackend, branchNameKey, repository, rw, pathGlob)) {
      while (treeWalk.next()) {
        CodeOwnerConfig codeOwnerConfig;
        try {
          codeOwnerConfig = treeWalk.getCodeOwnerConfig();
        } catch (CodeOwnersInternalServerErrorException codeOwnersInternalServerErrorException) {
          Optional<InvalidCodeOwnerConfigException> invalidCodeOwnerConfigException =
              getInvalidCodeOwnerConfigCause(codeOwnersInternalServerErrorException);
          if (!invalidCodeOwnerConfigException.isPresent()) {
            // Propagate any failure that is not related to the contents of the code owner config.
            throw codeOwnersInternalServerErrorException;
          }

          // The code owner config is invalid and cannot be parsed.
          invalidCodeOwnerConfigCallback.onInvalidCodeOwnerConfig(
              treeWalk.getFilePath(), invalidCodeOwnerConfigException.get());
          continue;
        }

        boolean visitFurtherCodeOwnerConfigFiles = codeOwnerConfigVisitor.visit(codeOwnerConfig);
        if (!visitFurtherCodeOwnerConfigFiles) {
          break;
        }
      }
    } catch (IOException e) {
      throw new CodeOwnersInternalServerErrorException(
          String.format(
              "Failed to scan for code owner configs in branch %s of project %s",
              branchNameKey.branch(), branchNameKey.project()),
          e);
    }
  }

  /**
   * Returns an {@link InvalidCodeOwnerConfigCallback} instance that ignores invalid code owner
   * config files.
   */
  public static InvalidCodeOwnerConfigCallback ignoreInvalidCodeOwnerConfigFiles() {
    return (codeOwnerConfigFilePath, configInvalidException) ->
        logger.atFine().log("ignoring invalid code owner config file %s", codeOwnerConfigFilePath);
  }
}
