// 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.CodeOwnersInternalServerErrorException.newInternalServerError;
import static java.util.Objects.requireNonNull;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Throwables;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Project;
import com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginConfiguration;
import com.google.gerrit.plugins.codeowners.backend.config.CodeOwnersPluginProjectConfigSnapshot;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.update.RetryHelper;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
import java.util.regex.Pattern;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevWalk;

/**
 * Base class for all {@link CodeOwnerBackend}'s that store {@link CodeOwnerConfig}'s in files
 * inside the corresponding folders in the source branch.
 *
 * <p>E.g. the code owner configuration for folder {@code /foo/bar} folder of the {@code master}
 * branch is stored as a file in the {@code /foo/bar} folder of the {@code master}
 */
public abstract class AbstractFileBasedCodeOwnerBackend implements CodeOwnerBackend {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final CodeOwnersPluginConfiguration codeOwnersPluginConfiguration;
  private final GitRepositoryManager repoManager;
  private final PersonIdent serverIdent;
  private final MetaDataUpdate.InternalFactory metaDataUpdateInternalFactory;
  private final RetryHelper retryHelper;
  private final String defaultFileName;
  private final CodeOwnerConfigFile.Factory codeOwnerConfigFileFactory;
  private final CodeOwnerConfigParser codeOwnerConfigParser;

  protected AbstractFileBasedCodeOwnerBackend(
      CodeOwnersPluginConfiguration codeOwnersPluginConfiguration,
      GitRepositoryManager repoManager,
      @GerritPersonIdent PersonIdent serverIdent,
      MetaDataUpdate.InternalFactory metaDataUpdateInternalFactory,
      RetryHelper retryHelper,
      String defaultFileName,
      CodeOwnerConfigFile.Factory codeOwnerConfigFileFactory,
      CodeOwnerConfigParser codeOwnerConfigParser) {
    this.codeOwnersPluginConfiguration = codeOwnersPluginConfiguration;
    this.repoManager = repoManager;
    this.serverIdent = serverIdent;
    this.metaDataUpdateInternalFactory = metaDataUpdateInternalFactory;
    this.retryHelper = retryHelper;
    this.defaultFileName = defaultFileName;
    this.codeOwnerConfigFileFactory = codeOwnerConfigFileFactory;
    this.codeOwnerConfigParser = codeOwnerConfigParser;
  }

  @Override
  public final Optional<CodeOwnerConfig> getCodeOwnerConfig(
      CodeOwnerConfig.Key codeOwnerConfigKey, @Nullable ObjectId revision) {
    String fileName =
        codeOwnerConfigKey.fileName().orElse(getFileName(codeOwnerConfigKey.project()));

    if (!isCodeOwnerConfigFile(codeOwnerConfigKey.project(), fileName)) {
      // The file name can mismatch if we resolve imported code owner configs. When code owner
      // configs are imported the user specifies the full path of the code owner config (including
      // the file name) in the importing code owner config. If the user specifies a file name that
      // is not supported, this is not a server error, but a user error. Invalid imports are
      // silently ignored, but users can detect them by running validation checks on the code owner
      // configs. Although this is a normal situation, still log a warning so that we can see in the
      // server logs when this happens.
      logger.atWarning().log(
          "Cannot load code owner config %s: unsupported file name", codeOwnerConfigKey);
      return Optional.empty();
    }

    return loadCodeOwnerConfigFile(codeOwnerConfigKey, fileName, revision)
        .getLoadedCodeOwnerConfig();
  }

  private CodeOwnerConfigFile loadCodeOwnerConfigFile(
      CodeOwnerConfig.Key codeOwnerConfigKey, String fileName, @Nullable ObjectId revision) {
    try (Repository repository = repoManager.openRepository(codeOwnerConfigKey.project())) {
      if (revision == null) {
        return codeOwnerConfigFileFactory.loadCurrent(
            fileName, codeOwnerConfigParser, repository, codeOwnerConfigKey);
      }

      try (RevWalk revWalk = new RevWalk(repository)) {
        return codeOwnerConfigFileFactory.load(
            fileName, codeOwnerConfigParser, revWalk, revision, codeOwnerConfigKey);
      }
    } catch (IOException e) {
      throw newInternalServerError(
          String.format("failed to load code owner config %s", codeOwnerConfigKey), e);
    } catch (ConfigInvalidException e) {
      throw newInternalServerError(
          String.format(
              "invalid code owner config file %s (project = %s, branch = %s)",
              codeOwnerConfigKey.filePath(defaultFileName),
              codeOwnerConfigKey.project(),
              codeOwnerConfigKey.branchNameKey().branch()),
          e);
    }
  }

  @Override
  public Path getFilePath(CodeOwnerConfig.Key codeOwnerConfigKey) {
    return codeOwnerConfigKey.filePath(defaultFileName);
  }

  @Override
  public boolean isCodeOwnerConfigFile(Project.NameKey project, String fileName) {
    requireNonNull(project, "project");
    requireNonNull(fileName, "fileName");

    if (getFileName(project).equals(fileName)) {
      return true;
    }

    return isCodeOwnerConfigFileWithExtension(project, fileName);
  }

  /**
   * Checks whether the given file name is code owner config file with an extension in the name.
   *
   * <p>Name extensions can appear as post- or pre-fix:
   *
   * <ul>
   *   <li>Post-fix: E.g. {@code OWNERS_<extension>} or {@code OWNERS_<extension>.<file-extension>}
   *   <li>Pre-fix: E.g. {@code <extension>_OWNERS} or {@code <extension>_OWNERS.<file-extension>}
   * </ul>
   *
   * @param project the project in which the code owner config files are stored
   * @param fileName the name of the file for which it should be checked whether is a code owner
   *     config file with extension
   * @return whether the given file name is code owner config file with an extension in the name
   */
  private boolean isCodeOwnerConfigFileWithExtension(Project.NameKey project, String fileName) {
    CodeOwnersPluginProjectConfigSnapshot codeOwnersPluginProjectConfigSnapshot =
        codeOwnersPluginConfiguration.getProjectConfig(project);
    String quotedDefaultFileName = Pattern.quote(defaultFileName);
    String quotedFileExtension =
        Pattern.quote(
            codeOwnersPluginProjectConfigSnapshot
                .getFileExtension()
                .map(ext -> "." + ext)
                .orElse(""));
    String nameExtension = "(\\w)+";

    return Pattern.compile(
                "^" + quotedDefaultFileName + "_" + nameExtension + quotedFileExtension + "$")
            .matcher(fileName)
            .matches()
        || Pattern.compile(
                "^" + nameExtension + "_" + quotedDefaultFileName + quotedFileExtension + "$")
            .matcher(fileName)
            .matches()
        || (codeOwnersPluginProjectConfigSnapshot.enableCodeOwnerConfigFilesWithFileExtensions()
            && Pattern.compile(
                    "^" + quotedDefaultFileName + Pattern.quote(".") + nameExtension + "$")
                .matcher(fileName)
                .matches());
  }

  private String getFileName(Project.NameKey project) {
    return defaultFileName
        + codeOwnersPluginConfiguration
            .getProjectConfig(project)
            .getFileExtension()
            .map(ext -> "." + ext)
            .orElse("");
  }

  @Override
  public final Optional<CodeOwnerConfig> upsertCodeOwnerConfig(
      CodeOwnerConfig.Key codeOwnerConfigKey,
      CodeOwnerConfigUpdate codeOwnerConfigUpdate,
      @Nullable IdentifiedUser currentUser) {
    try {
      return retryHelper
          .pluginUpdate(
              "upsertCodeOwnerConfigInSourceBranch",
              () ->
                  upsertCodeOwnerConfigInSourceBranch(
                      currentUser, codeOwnerConfigKey, codeOwnerConfigUpdate))
          .call();
    } catch (Exception e) {
      Throwables.throwIfUnchecked(e);
      throw newInternalServerError(
          String.format("failed to upsert code owner config %s", codeOwnerConfigKey), e);
    }
  }

  @Override
  public final Optional<PathExpressionMatcher> getPathExpressionMatcher(
      BranchNameKey branchNameKey) {
    Optional<PathExpressions> pathExpressions =
        codeOwnersPluginConfiguration
            .getProjectConfig(branchNameKey.project())
            .getPathExpressions(branchNameKey.branch());
    boolean hasConfiguredPathExpressions = pathExpressions.isPresent();
    if (!hasConfiguredPathExpressions) {
      pathExpressions = getDefaultPathExpressions();
    }
    logger.atFine().log(
        "using %s path expression syntax %s for project/branch %s",
        (hasConfiguredPathExpressions ? "configured" : "default"),
        pathExpressions.map(PathExpressions::name).orElse("<none>"),
        branchNameKey);
    return pathExpressions.map(PathExpressions::getMatcher);
  }

  @VisibleForTesting
  public abstract Optional<PathExpressions> getDefaultPathExpressions();

  private Optional<CodeOwnerConfig> upsertCodeOwnerConfigInSourceBranch(
      @Nullable IdentifiedUser currentUser,
      CodeOwnerConfig.Key codeOwnerConfigKey,
      CodeOwnerConfigUpdate codeOwnerConfigUpdate) {
    try (Repository repository = repoManager.openRepository(codeOwnerConfigKey.project())) {
      CodeOwnerConfigFile codeOwnerConfigFile =
          codeOwnerConfigFileFactory
              .loadCurrent(
                  getFileName(codeOwnerConfigKey.project()),
                  codeOwnerConfigParser,
                  repository,
                  codeOwnerConfigKey)
              .setCodeOwnerConfigUpdate(codeOwnerConfigUpdate);

      try (MetaDataUpdate metaDataUpdate =
          createMetaDataUpdate(codeOwnerConfigKey.project(), repository, currentUser)) {
        codeOwnerConfigFile.commit(metaDataUpdate);
      }

      return codeOwnerConfigFile.getLoadedCodeOwnerConfig();
    } catch (IOException | ConfigInvalidException e) {
      throw newInternalServerError(
          String.format("failed to upsert code owner config %s", codeOwnerConfigKey), e);
    }
  }

  private MetaDataUpdate createMetaDataUpdate(
      Project.NameKey project, Repository repository, @Nullable IdentifiedUser currentUser) {
    MetaDataUpdate metaDataUpdate = metaDataUpdateInternalFactory.create(project, repository, null);
    try {
      metaDataUpdate.getCommitBuilder().setCommitter(serverIdent);
      if (currentUser != null) {
        // Using MetaDataUpdate#setAuthor copies the timezone and timestamp from the committer
        // identity, so that it's ensured that the author and committer identities have the same
        // timezone and timestamp.
        metaDataUpdate.setAuthor(currentUser);
      } else {
        // In this case the author identity is the same as the committer identity, hence it already
        // has the correct timezone and timestamp and we can set it on the commit builder directly.
        metaDataUpdate.getCommitBuilder().setAuthor(serverIdent);
      }
      return metaDataUpdate;
    } catch (Exception e) {
      throw newInternalServerError("Failed to create MetaDataUpdate", e);
    } finally {
      metaDataUpdate.close();
    }
  }
}
