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

import static com.google.common.collect.ImmutableList.toImmutableList;
import static java.util.Objects.requireNonNull;

import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerBackend;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfig;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfigScanner;
import com.google.gerrit.plugins.codeowners.config.CodeOwnersPluginConfiguration;
import com.google.gerrit.server.project.BranchResource;
import com.google.inject.Inject;
import java.nio.file.Path;
import java.util.List;
import org.kohsuke.args4j.Option;

/**
 * REST endpoint that lists the code owner config files in a branch.
 *
 * <p>This REST endpoint handles {@code GET
 * /projects/<project-name>/branches/<branch-name>/code_owners.config/} requests.
 *
 * <p>The implementation of this REST endpoint iterates over all code owner config files in the
 * branch. This means the expected performance of this REST endpoint is rather low and it should not
 * be used in any critical path where performance matters.
 */
public class GetCodeOwnerConfigFiles implements RestReadView<BranchResource> {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final CodeOwnersPluginConfiguration codeOwnersPluginConfiguration;
  private final CodeOwnerConfigScanner.Factory codeOwnerConfigScannerFactory;

  private boolean includeNonParsableFiles;
  private String email;
  private String pathGlob;

  @Option(
      name = "--include-non-parsable-files",
      usage = "includes non-parseable code owner config files in the response")
  public void setIncludeNonParsableFiles(boolean includeNonParsableFiles) {
    this.includeNonParsableFiles = includeNonParsableFiles;
  }

  @Option(
      name = "--email",
      metaVar = "EMAIL",
      usage = "limits the returned code owner config files to those that contain this email")
  public void setEmail(@Nullable String email) {
    this.email = email;
  }

  @Option(
      name = "--path",
      usage =
          "limits the returned code owner config files to those that have a path matching"
              + " this glob")
  public void setPath(@Nullable String pathGlob) {
    this.pathGlob = pathGlob;
  }

  @Inject
  public GetCodeOwnerConfigFiles(
      CodeOwnersPluginConfiguration codeOwnersPluginConfiguration,
      CodeOwnerConfigScanner.Factory codeOwnerConfigScannerFactory) {
    this.codeOwnersPluginConfiguration = codeOwnersPluginConfiguration;
    this.codeOwnerConfigScannerFactory = codeOwnerConfigScannerFactory;
  }

  @Override
  public Response<List<String>> apply(BranchResource resource) throws BadRequestException {
    validateOptions();

    CodeOwnerBackend codeOwnerBackend =
        codeOwnersPluginConfiguration.getBackend(resource.getBranchKey());
    ImmutableList.Builder<Path> codeOwnerConfigs = ImmutableList.builder();

    if (email != null) {
      logger.atFine().log(
          "limiting the returned code owner config files to those that contain the email %s",
          email);
    }

    codeOwnerConfigScannerFactory
        .create()
        // Do not include the default code owner config file in refs/meta/config, as this config is
        // stored in another branch. If it should be listed users must list the code owner config
        // files in refs/meta/config explicitly.
        .includeDefaultCodeOwnerConfig(false)
        .visit(
            resource.getBranchKey(),
            codeOwnerConfig -> {
              Path codeOwnerConfigPath = codeOwnerBackend.getFilePath(codeOwnerConfig.key());
              if (email == null || containsEmail(codeOwnerConfig, codeOwnerConfigPath, email)) {
                codeOwnerConfigs.add(codeOwnerConfigPath);
              }
              return true;
            },
            includeNonParsableFiles
                ? (codeOwnerConfigFilePath, configInvalidException) -> {
                  codeOwnerConfigs.add(codeOwnerConfigFilePath);
                }
                : CodeOwnerConfigScanner.ignoreInvalidCodeOwnerConfigFiles(),
            pathGlob);
    return Response.ok(
        codeOwnerConfigs.build().stream().map(Path::toString).collect(toImmutableList()));
  }

  /**
   * Checks whether the given code owner config contains the given email.
   *
   * @param codeOwnerConfig the code owner config for which it should be checked if it contains the
   *     email
   * @param codeOwnerConfigPath the path of the code owner config
   * @param email the email
   * @return whether the given code owner config contains the given email
   */
  private boolean containsEmail(
      CodeOwnerConfig codeOwnerConfig, Path codeOwnerConfigPath, String email) {
    requireNonNull(email, "email");
    boolean containsEmail =
        codeOwnerConfig.codeOwnerSets().stream()
            .flatMap(codeOwnerSet -> codeOwnerSet.codeOwners().stream())
            .anyMatch(codeOwnerReference -> email.equals(codeOwnerReference.email()));
    if (!containsEmail) {
      logger.atFine().log(
          "Filtering out %s since it doesn't contain the email", codeOwnerConfigPath);
    }
    return containsEmail;
  }

  private void validateOptions() throws BadRequestException {
    if (email != null && includeNonParsableFiles) {
      throw new BadRequestException(
          "the options 'email' and 'include-non-parsable-files' are mutually exclusive");
    }
  }
}
