// Copyright (C) 2017 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.server.group.db;

import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.InternalGroup;
import com.google.gerrit.entities.Project;
import com.google.gerrit.exceptions.DuplicateKeyException;
import com.google.gerrit.exceptions.NoSuchGroupException;
import com.google.gerrit.git.RefUpdateUtil;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.account.GroupIncludeCache;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.GerritServerId;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.group.GroupAuditService;
import com.google.gerrit.server.index.group.GroupIndexer;
import com.google.gerrit.server.logging.Metadata;
import com.google.gerrit.server.logging.TraceContext;
import com.google.gerrit.server.logging.TraceContext.TraceTimer;
import com.google.gerrit.server.update.RetryHelper;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import java.io.IOException;
import java.time.Instant;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;

/**
 * A database accessor for write calls related to groups.
 *
 * <p>All calls which write group related details to the database are gathered here. Other classes
 * should always use this class instead of accessing the database directly. There are a few
 * exceptions though: schema classes, wrapper classes, and classes executed during init. The latter
 * ones should use {@link com.google.gerrit.pgm.init.GroupsOnInit} instead.
 *
 * <p>If not explicitly stated, all methods of this class refer to <em>internal</em> groups.
 */
public class GroupsUpdate {
  public interface Factory {
    /**
     * Creates a {@link GroupsUpdate} which uses the identity of the specified user to mark database
     * modifications executed by it. For NoteDb, this identity is used as author and committer for
     * all related commits.
     *
     * <p><strong>Note</strong>: Please use this method with care and consider using the {@link
     * com.google.gerrit.server.UserInitiated} annotation on the provider of a {@link GroupsUpdate}
     * instead.
     *
     * @param currentUser the user to which modifications should be attributed
     */
    GroupsUpdate create(IdentifiedUser currentUser);

    /**
     * Creates a {@link GroupsUpdate} which uses the server identity to mark database modifications
     * executed by it. For NoteDb, this identity is used as author and committer for all related
     * commits.
     *
     * <p><strong>Note</strong>: Please use this method with care and consider using the {@link
     * com.google.gerrit.server.ServerInitiated} annotation on the provider of a {@link
     * GroupsUpdate} instead.
     */
    GroupsUpdate createWithServerIdent();
  }

  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final GitRepositoryManager repoManager;
  private final AllUsersName allUsersName;
  private final GroupCache groupCache;
  private final GroupIncludeCache groupIncludeCache;
  private final Provider<GroupIndexer> indexer;
  private final GroupAuditService groupAuditService;
  private final RenameGroupOp.Factory renameGroupOpFactory;
  private final Optional<IdentifiedUser> currentUser;
  private final AuditLogFormatter auditLogFormatter;
  private final PersonIdent authorIdent;
  private final MetaDataUpdateFactory metaDataUpdateFactory;
  private final GitReferenceUpdated gitRefUpdated;
  private final RetryHelper retryHelper;

  @AssistedInject
  @SuppressWarnings("BindingAnnotationWithoutInject")
  GroupsUpdate(
      GitRepositoryManager repoManager,
      AllUsersName allUsersName,
      GroupBackend groupBackend,
      GroupCache groupCache,
      GroupIncludeCache groupIncludeCache,
      Provider<GroupIndexer> indexer,
      GroupAuditService auditService,
      AccountCache accountCache,
      RenameGroupOp.Factory renameGroupOpFactory,
      @GerritServerId String serverId,
      @GerritPersonIdent PersonIdent serverIdent,
      MetaDataUpdate.InternalFactory metaDataUpdateInternalFactory,
      GitReferenceUpdated gitRefUpdated,
      RetryHelper retryHelper) {
    this(
        repoManager,
        allUsersName,
        groupBackend,
        groupCache,
        groupIncludeCache,
        indexer,
        auditService,
        accountCache,
        renameGroupOpFactory,
        serverId,
        serverIdent,
        metaDataUpdateInternalFactory,
        gitRefUpdated,
        retryHelper,
        Optional.empty());
  }

  @AssistedInject
  @SuppressWarnings("BindingAnnotationWithoutInject")
  GroupsUpdate(
      GitRepositoryManager repoManager,
      AllUsersName allUsersName,
      GroupBackend groupBackend,
      GroupCache groupCache,
      GroupIncludeCache groupIncludeCache,
      Provider<GroupIndexer> indexer,
      GroupAuditService auditService,
      AccountCache accountCache,
      RenameGroupOp.Factory renameGroupOpFactory,
      @GerritServerId String serverId,
      @GerritPersonIdent PersonIdent serverIdent,
      MetaDataUpdate.InternalFactory metaDataUpdateInternalFactory,
      GitReferenceUpdated gitRefUpdated,
      RetryHelper retryHelper,
      @Assisted IdentifiedUser currentUser) {
    this(
        repoManager,
        allUsersName,
        groupBackend,
        groupCache,
        groupIncludeCache,
        indexer,
        auditService,
        accountCache,
        renameGroupOpFactory,
        serverId,
        serverIdent,
        metaDataUpdateInternalFactory,
        gitRefUpdated,
        retryHelper,
        Optional.of(currentUser));
  }

  @SuppressWarnings("BindingAnnotationWithoutInject")
  private GroupsUpdate(
      GitRepositoryManager repoManager,
      AllUsersName allUsersName,
      GroupBackend groupBackend,
      GroupCache groupCache,
      GroupIncludeCache groupIncludeCache,
      Provider<GroupIndexer> indexer,
      GroupAuditService auditService,
      AccountCache accountCache,
      RenameGroupOp.Factory renameGroupOpFactory,
      @GerritServerId String serverId,
      @GerritPersonIdent PersonIdent serverIdent,
      MetaDataUpdate.InternalFactory metaDataUpdateInternalFactory,
      GitReferenceUpdated gitRefUpdated,
      RetryHelper retryHelper,
      Optional<IdentifiedUser> currentUser) {
    this.repoManager = repoManager;
    this.allUsersName = allUsersName;
    this.groupCache = groupCache;
    this.groupIncludeCache = groupIncludeCache;
    this.indexer = indexer;
    this.groupAuditService = auditService;
    this.renameGroupOpFactory = renameGroupOpFactory;
    this.gitRefUpdated = gitRefUpdated;
    this.retryHelper = retryHelper;
    this.currentUser = currentUser;

    auditLogFormatter = AuditLogFormatter.createBackedBy(accountCache, groupBackend, serverId);
    metaDataUpdateFactory =
        getMetaDataUpdateFactory(
            metaDataUpdateInternalFactory, currentUser, serverIdent, auditLogFormatter);
    authorIdent = getAuthorIdent(serverIdent, currentUser);
  }

  private static MetaDataUpdateFactory getMetaDataUpdateFactory(
      MetaDataUpdate.InternalFactory metaDataUpdateInternalFactory,
      Optional<IdentifiedUser> currentUser,
      PersonIdent serverIdent,
      AuditLogFormatter auditLogFormatter) {
    return (projectName, repository, batchRefUpdate) -> {
      MetaDataUpdate metaDataUpdate =
          metaDataUpdateInternalFactory.create(projectName, repository, batchRefUpdate);
      metaDataUpdate.getCommitBuilder().setCommitter(serverIdent);
      PersonIdent authorIdent;
      if (currentUser.isPresent()) {
        metaDataUpdate.setAuthor(currentUser.get());
        authorIdent =
            auditLogFormatter.getParsableAuthorIdent(currentUser.get().getAccount(), serverIdent);
      } else {
        authorIdent = serverIdent;
      }
      metaDataUpdate.getCommitBuilder().setAuthor(authorIdent);
      return metaDataUpdate;
    };
  }

  private static PersonIdent getAuthorIdent(
      PersonIdent serverIdent, Optional<IdentifiedUser> currentUser) {
    return currentUser.map(user -> createPersonIdent(serverIdent, user)).orElse(serverIdent);
  }

  private static PersonIdent createPersonIdent(PersonIdent ident, IdentifiedUser user) {
    return user.newCommitterIdent(ident);
  }

  /**
   * Creates the specified group for the specified members (accounts).
   *
   * @param groupCreation an {@link InternalGroupCreation} which specifies all mandatory properties
   *     of the group
   * @param groupDelta a {@link GroupDelta} which specifies optional properties of the group. If
   *     this {@link GroupDelta} updates a property which was already specified by the {@link
   *     InternalGroupCreation}, the value of this {@link GroupDelta} wins.
   * @throws DuplicateKeyException if a group with the chosen name already exists
   * @throws IOException if indexing fails, or an error occurs while reading/writing from/to NoteDb
   * @return the created {@link InternalGroup}
   */
  public InternalGroup createGroup(InternalGroupCreation groupCreation, GroupDelta groupDelta)
      throws DuplicateKeyException, IOException, ConfigInvalidException {
    try (TraceTimer ignored =
        TraceContext.newTimer(
            "Creating group",
            Metadata.builder()
                .groupName(groupDelta.getName().orElseGet(groupCreation::getNameKey).get())
                .build())) {
      InternalGroup createdGroup = createGroupInNoteDbWithRetry(groupCreation, groupDelta);
      evictCachesOnGroupCreation(createdGroup);
      dispatchAuditEventsOnGroupCreation(createdGroup);
      return createdGroup;
    }
  }

  /**
   * Updates the specified group.
   *
   * @param groupUuid the UUID of the group to update
   * @param groupDelta a {@link GroupDelta} which indicates the desired updates on the group
   * @throws DuplicateKeyException if the new name of the group is used by another group
   * @throws IOException if indexing fails, or an error occurs while reading/writing from/to NoteDb
   * @throws NoSuchGroupException if the specified group doesn't exist
   */
  public void updateGroup(AccountGroup.UUID groupUuid, GroupDelta groupDelta)
      throws DuplicateKeyException, IOException, NoSuchGroupException, ConfigInvalidException {
    try (TraceTimer ignored =
        TraceContext.newTimer(
            "Updating group", Metadata.builder().groupUuid(groupUuid.get()).build())) {
      Optional<Instant> updatedOn = groupDelta.getUpdatedOn();
      if (!updatedOn.isPresent()) {
        updatedOn = Optional.of(TimeUtil.now());
        groupDelta = groupDelta.toBuilder().setUpdatedOn(updatedOn.get()).build();
      }

      UpdateResult result = updateGroupInNoteDbWithRetry(groupUuid, groupDelta);
      updateNameInProjectConfigsIfNecessary(result);
      evictCachesOnGroupUpdate(result);
      dispatchAuditEventsOnGroupUpdate(result, updatedOn.get());
    }
  }

  private InternalGroup createGroupInNoteDbWithRetry(
      InternalGroupCreation groupCreation, GroupDelta groupDelta)
      throws IOException, ConfigInvalidException, DuplicateKeyException {
    try {
      return retryHelper
          .groupUpdate("createGroup", () -> createGroupInNoteDb(groupCreation, groupDelta))
          .call();
    } catch (Exception e) {
      Throwables.throwIfUnchecked(e);
      Throwables.throwIfInstanceOf(e, IOException.class);
      Throwables.throwIfInstanceOf(e, ConfigInvalidException.class);
      Throwables.throwIfInstanceOf(e, DuplicateKeyException.class);
      throw new IOException(e);
    }
  }

  @VisibleForTesting
  public InternalGroup createGroupInNoteDb(
      InternalGroupCreation groupCreation, GroupDelta groupDelta)
      throws IOException, ConfigInvalidException, DuplicateKeyException {
    try (Repository allUsersRepo = repoManager.openRepository(allUsersName)) {
      AccountGroup.NameKey groupName = groupDelta.getName().orElseGet(groupCreation::getNameKey);
      GroupNameNotes groupNameNotes =
          GroupNameNotes.forNewGroup(
              allUsersName, allUsersRepo, groupCreation.getGroupUUID(), groupName);

      GroupConfig groupConfig =
          GroupConfig.createForNewGroup(allUsersName, allUsersRepo, groupCreation);
      groupConfig.setGroupDelta(groupDelta, auditLogFormatter);

      commit(allUsersRepo, groupConfig, groupNameNotes);

      return groupConfig
          .getLoadedGroup()
          .orElseThrow(
              () -> new IllegalStateException("Created group wasn't automatically loaded"));
    }
  }

  private UpdateResult updateGroupInNoteDbWithRetry(
      AccountGroup.UUID groupUuid, GroupDelta groupDelta)
      throws IOException, ConfigInvalidException, DuplicateKeyException, NoSuchGroupException {
    try {
      return retryHelper
          .groupUpdate("updateGroup", () -> updateGroupInNoteDb(groupUuid, groupDelta))
          .call();
    } catch (Exception e) {
      Throwables.throwIfUnchecked(e);
      Throwables.throwIfInstanceOf(e, IOException.class);
      Throwables.throwIfInstanceOf(e, ConfigInvalidException.class);
      Throwables.throwIfInstanceOf(e, DuplicateKeyException.class);
      Throwables.throwIfInstanceOf(e, NoSuchGroupException.class);
      throw new IOException(e);
    }
  }

  @VisibleForTesting
  public UpdateResult updateGroupInNoteDb(AccountGroup.UUID groupUuid, GroupDelta groupDelta)
      throws IOException, ConfigInvalidException, DuplicateKeyException, NoSuchGroupException {
    try (Repository allUsersRepo = repoManager.openRepository(allUsersName)) {
      GroupConfig groupConfig = GroupConfig.loadForGroup(allUsersName, allUsersRepo, groupUuid);
      groupConfig.setGroupDelta(groupDelta, auditLogFormatter);
      if (!groupConfig.getLoadedGroup().isPresent()) {
        throw new NoSuchGroupException(groupUuid);
      }

      InternalGroup originalGroup = groupConfig.getLoadedGroup().get();
      GroupNameNotes groupNameNotes = null;
      if (groupDelta.getName().isPresent()) {
        AccountGroup.NameKey oldName = originalGroup.getNameKey();
        AccountGroup.NameKey newName = groupDelta.getName().get();
        groupNameNotes =
            GroupNameNotes.forRename(allUsersName, allUsersRepo, groupUuid, oldName, newName);
      }

      commit(allUsersRepo, groupConfig, groupNameNotes);

      InternalGroup updatedGroup =
          groupConfig
              .getLoadedGroup()
              .orElseThrow(
                  () -> new IllegalStateException("Updated group wasn't automatically loaded"));
      return getUpdateResult(originalGroup, updatedGroup);
    }
  }

  private static UpdateResult getUpdateResult(
      InternalGroup originalGroup, InternalGroup updatedGroup) {
    Set<Account.Id> addedMembers =
        Sets.difference(updatedGroup.getMembers(), originalGroup.getMembers());
    Set<Account.Id> deletedMembers =
        Sets.difference(originalGroup.getMembers(), updatedGroup.getMembers());
    Set<AccountGroup.UUID> addedSubgroups =
        Sets.difference(updatedGroup.getSubgroups(), originalGroup.getSubgroups());
    Set<AccountGroup.UUID> deletedSubgroups =
        Sets.difference(originalGroup.getSubgroups(), updatedGroup.getSubgroups());

    UpdateResult.Builder resultBuilder =
        UpdateResult.builder()
            .setGroupUuid(updatedGroup.getGroupUUID())
            .setGroupId(updatedGroup.getId())
            .setGroupName(updatedGroup.getNameKey())
            .setAddedMembers(addedMembers)
            .setDeletedMembers(deletedMembers)
            .setAddedSubgroups(addedSubgroups)
            .setDeletedSubgroups(deletedSubgroups);
    if (!Objects.equals(originalGroup.getNameKey(), updatedGroup.getNameKey())) {
      resultBuilder.setPreviousGroupName(originalGroup.getNameKey());
    }
    return resultBuilder.build();
  }

  private void commit(
      Repository allUsersRepo, GroupConfig groupConfig, @Nullable GroupNameNotes groupNameNotes)
      throws IOException {
    BatchRefUpdate batchRefUpdate = allUsersRepo.getRefDatabase().newBatchUpdate();
    try (MetaDataUpdate metaDataUpdate =
        metaDataUpdateFactory.create(allUsersName, allUsersRepo, batchRefUpdate)) {
      groupConfig.commit(metaDataUpdate);
    }
    if (groupNameNotes != null) {
      // MetaDataUpdates unfortunately can't be reused. -> Create a new one.
      try (MetaDataUpdate metaDataUpdate =
          metaDataUpdateFactory.create(allUsersName, allUsersRepo, batchRefUpdate)) {
        groupNameNotes.commit(metaDataUpdate);
      }
    }

    RefUpdateUtil.executeChecked(batchRefUpdate, allUsersRepo);
    gitRefUpdated.fire(
        allUsersName, batchRefUpdate, currentUser.map(user -> user.state()).orElse(null));
  }

  private void evictCachesOnGroupCreation(InternalGroup createdGroup) {
    logger.atFine().log("evict caches on creation of group %s", createdGroup.getGroupUUID());
    // By UUID is used for the index and hence should be evicted before refreshing the index.
    groupCache.evict(createdGroup.getGroupUUID());
    indexer.get().index(createdGroup.getGroupUUID());
    // These caches use the result from the index and hence must be evicted after refreshing the
    // index.
    groupCache.evict(createdGroup.getId());
    groupCache.evict(createdGroup.getNameKey());
    createdGroup.getMembers().forEach(groupIncludeCache::evictGroupsWithMember);
    createdGroup.getSubgroups().forEach(groupIncludeCache::evictParentGroupsOf);
  }

  private void evictCachesOnGroupUpdate(UpdateResult result) {
    logger.atFine().log("evict caches on update of group %s", result.getGroupUuid());
    // By UUID is used for the index and hence should be evicted before refreshing the index.
    groupCache.evict(result.getGroupUuid());
    indexer.get().index(result.getGroupUuid());
    // These caches use the result from the index and hence must be evicted after refreshing the
    // index.
    groupCache.evict(result.getGroupId());
    groupCache.evict(result.getGroupName());
    result.getPreviousGroupName().ifPresent(groupCache::evict);

    result.getAddedMembers().forEach(groupIncludeCache::evictGroupsWithMember);
    result.getDeletedMembers().forEach(groupIncludeCache::evictGroupsWithMember);
    result.getAddedSubgroups().forEach(groupIncludeCache::evictParentGroupsOf);
    result.getDeletedSubgroups().forEach(groupIncludeCache::evictParentGroupsOf);
  }

  private void updateNameInProjectConfigsIfNecessary(UpdateResult result) {
    if (result.getPreviousGroupName().isPresent()) {
      AccountGroup.NameKey previousName = result.getPreviousGroupName().get();

      @SuppressWarnings("unused")
      Future<?> possiblyIgnoredError =
          renameGroupOpFactory
              .create(
                  authorIdent,
                  result.getGroupUuid(),
                  previousName.get(),
                  result.getGroupName().get())
              .start(0, TimeUnit.MILLISECONDS);
    }
  }

  private void dispatchAuditEventsOnGroupCreation(InternalGroup createdGroup) {
    if (!currentUser.isPresent()) {
      return;
    }

    if (!createdGroup.getMembers().isEmpty()) {
      groupAuditService.dispatchAddMembers(
          currentUser.get().getAccountId(),
          createdGroup.getGroupUUID(),
          createdGroup.getMembers(),
          createdGroup.getCreatedOn());
    }
    if (!createdGroup.getSubgroups().isEmpty()) {
      groupAuditService.dispatchAddSubgroups(
          currentUser.get().getAccountId(),
          createdGroup.getGroupUUID(),
          createdGroup.getSubgroups(),
          createdGroup.getCreatedOn());
    }
  }

  private void dispatchAuditEventsOnGroupUpdate(UpdateResult result, Instant updatedOn) {
    if (!currentUser.isPresent()) {
      return;
    }

    if (!result.getAddedMembers().isEmpty()) {
      groupAuditService.dispatchAddMembers(
          currentUser.get().getAccountId(),
          result.getGroupUuid(),
          result.getAddedMembers(),
          updatedOn);
    }
    if (!result.getDeletedMembers().isEmpty()) {
      groupAuditService.dispatchDeleteMembers(
          currentUser.get().getAccountId(),
          result.getGroupUuid(),
          result.getDeletedMembers(),
          updatedOn);
    }
    if (!result.getAddedSubgroups().isEmpty()) {
      groupAuditService.dispatchAddSubgroups(
          currentUser.get().getAccountId(),
          result.getGroupUuid(),
          result.getAddedSubgroups(),
          updatedOn);
    }
    if (!result.getDeletedSubgroups().isEmpty()) {
      groupAuditService.dispatchDeleteSubgroups(
          currentUser.get().getAccountId(),
          result.getGroupUuid(),
          result.getDeletedSubgroups(),
          updatedOn);
    }
  }

  @FunctionalInterface
  private interface MetaDataUpdateFactory {
    MetaDataUpdate create(
        Project.NameKey projectName, Repository repository, BatchRefUpdate batchRefUpdate)
        throws IOException;
  }

  @AutoValue
  abstract static class UpdateResult {
    abstract AccountGroup.UUID getGroupUuid();

    abstract AccountGroup.Id getGroupId();

    abstract AccountGroup.NameKey getGroupName();

    abstract Optional<AccountGroup.NameKey> getPreviousGroupName();

    abstract ImmutableSet<Account.Id> getAddedMembers();

    abstract ImmutableSet<Account.Id> getDeletedMembers();

    abstract ImmutableSet<AccountGroup.UUID> getAddedSubgroups();

    abstract ImmutableSet<AccountGroup.UUID> getDeletedSubgroups();

    static Builder builder() {
      return new AutoValue_GroupsUpdate_UpdateResult.Builder();
    }

    @AutoValue.Builder
    abstract static class Builder {
      abstract Builder setGroupUuid(AccountGroup.UUID groupUuid);

      abstract Builder setGroupId(AccountGroup.Id groupId);

      abstract Builder setGroupName(AccountGroup.NameKey name);

      abstract Builder setPreviousGroupName(AccountGroup.NameKey previousName);

      abstract Builder setAddedMembers(Set<Account.Id> addedMembers);

      abstract Builder setDeletedMembers(Set<Account.Id> deletedMembers);

      abstract Builder setAddedSubgroups(Set<AccountGroup.UUID> addedSubgroups);

      abstract Builder setDeletedSubgroups(Set<AccountGroup.UUID> deletedSubgroups);

      abstract UpdateResult build();
    }
  }
}
