// 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 static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.gerrit.server.group.db.Groups.getExistingGroupFromReviewDb;

import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.AccountGroupById;
import com.google.gerrit.reviewdb.client.AccountGroupMember;
import com.google.gerrit.reviewdb.client.AccountGroupName;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.reviewdb.server.ReviewDbUtil;
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.audit.AuditService;
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.LockFailureException;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.RenameGroupOp;
import com.google.gerrit.server.group.InternalGroup;
import com.google.gerrit.server.index.group.GroupIndexer;
import com.google.gerrit.server.notedb.GroupsMigration;
import com.google.gerrit.server.update.RefUpdateUtil;
import com.google.gerrit.server.update.RetryHelper;
import com.google.gwtorm.server.OrmDuplicateKeyException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
import java.sql.Timestamp;
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.ObjectId;
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 (either ReviewDb or NoteDb) 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 {@code 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 {@code 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 rather consider to use the
     * correct annotation on the provider of a {@code GroupsUpdate} instead.
     *
     * @param currentUser the user to which modifications should be attributed, or {@code null} if
     *     the Gerrit server identity should be used
     */
    GroupsUpdate create(@Nullable IdentifiedUser currentUser);
  }

  private final GitRepositoryManager repoManager;
  private final AllUsersName allUsersName;
  private final GroupCache groupCache;
  private final GroupIncludeCache groupIncludeCache;
  private final Provider<GroupIndexer> indexer;
  private final AuditService auditService;
  private final RenameGroupOp.Factory renameGroupOpFactory;
  @Nullable private final IdentifiedUser currentUser;
  private final AuditLogFormatter auditLogFormatter;
  private final PersonIdent authorIdent;
  private final MetaDataUpdateFactory metaDataUpdateFactory;
  private final GroupsMigration groupsMigration;
  private final GitReferenceUpdated gitRefUpdated;
  private final RetryHelper retryHelper;

  @Inject
  GroupsUpdate(
      GitRepositoryManager repoManager,
      AllUsersName allUsersName,
      GroupBackend groupBackend,
      GroupCache groupCache,
      GroupIncludeCache groupIncludeCache,
      Provider<GroupIndexer> indexer,
      AuditService auditService,
      AccountCache accountCache,
      RenameGroupOp.Factory renameGroupOpFactory,
      @GerritServerId String serverId,
      @GerritPersonIdent PersonIdent serverIdent,
      MetaDataUpdate.InternalFactory metaDataUpdateInternalFactory,
      GroupsMigration groupsMigration,
      GitReferenceUpdated gitRefUpdated,
      RetryHelper retryHelper,
      @Assisted @Nullable IdentifiedUser currentUser) {
    this.repoManager = repoManager;
    this.allUsersName = allUsersName;
    this.groupCache = groupCache;
    this.groupIncludeCache = groupIncludeCache;
    this.indexer = indexer;
    this.auditService = auditService;
    this.renameGroupOpFactory = renameGroupOpFactory;
    this.groupsMigration = groupsMigration;
    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,
      @Nullable 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 != null) {
        metaDataUpdate.setAuthor(currentUser);
        authorIdent =
            auditLogFormatter.getParsableAuthorIdent(currentUser.getAccount(), serverIdent);
      } else {
        authorIdent = serverIdent;
      }
      metaDataUpdate.getCommitBuilder().setAuthor(authorIdent);
      return metaDataUpdate;
    };
  }

  private static PersonIdent getAuthorIdent(
      PersonIdent serverIdent, @Nullable IdentifiedUser currentUser) {
    return currentUser != null ? createPersonIdent(serverIdent, currentUser) : serverIdent;
  }

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

  /**
   * Creates the specified group for the specified members (accounts).
   *
   * @param db the {@code ReviewDb} instance to update
   * @param groupCreation an {@code InternalGroupCreation} which specifies all mandatory properties
   *     of the group
   * @param groupUpdate an {@code InternalGroupUpdate} which specifies optional properties of the
   *     group. If this {@code InternalGroupUpdate} updates a property which was already specified
   *     by the {@code InternalGroupCreation}, the value of this {@code InternalGroupUpdate} wins.
   * @throws OrmException if an error occurs while reading/writing from/to ReviewDb
   * @throws OrmDuplicateKeyException 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 {@code InternalGroup}
   */
  public InternalGroup createGroup(
      ReviewDb db, InternalGroupCreation groupCreation, InternalGroupUpdate groupUpdate)
      throws OrmException, IOException, ConfigInvalidException {
    if (!groupsMigration.disableGroupReviewDb()) {
      if (!groupUpdate.getUpdatedOn().isPresent()) {
        // Set updatedOn to a specific value so that the same timestamp is used for ReviewDb and
        // NoteDb.
        groupUpdate = groupUpdate.toBuilder().setUpdatedOn(TimeUtil.nowTs()).build();
      }

      InternalGroup createdGroupInReviewDb =
          createGroupInReviewDb(ReviewDbUtil.unwrapDb(db), groupCreation, groupUpdate);

      if (!groupsMigration.writeToNoteDb()) {
        updateCachesOnGroupCreation(createdGroupInReviewDb);
        dispatchAuditEventsOnGroupCreation(createdGroupInReviewDb);
        return createdGroupInReviewDb;
      }
    }

    InternalGroup createdGroup = createGroupInNoteDbWithRetry(groupCreation, groupUpdate);
    updateCachesOnGroupCreation(createdGroup);
    dispatchAuditEventsOnGroupCreation(createdGroup);
    return createdGroup;
  }

  /**
   * Updates the specified group.
   *
   * @param db the {@code ReviewDb} instance to update
   * @param groupUuid the UUID of the group to update
   * @param groupUpdate an {@code InternalGroupUpdate} which indicates the desired updates on the
   *     group
   * @throws OrmException if an error occurs while reading/writing from/to ReviewDb
   * @throws com.google.gwtorm.server.OrmDuplicateKeyException 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(ReviewDb db, AccountGroup.UUID groupUuid, InternalGroupUpdate groupUpdate)
      throws OrmException, IOException, NoSuchGroupException, ConfigInvalidException {
    Optional<Timestamp> updatedOn = groupUpdate.getUpdatedOn();
    if (!updatedOn.isPresent()) {
      // Set updatedOn to a specific value so that the same timestamp is used for ReviewDb and
      // NoteDb. This timestamp is also used by audit events.
      updatedOn = Optional.of(TimeUtil.nowTs());
      groupUpdate = groupUpdate.toBuilder().setUpdatedOn(updatedOn.get()).build();
    }

    UpdateResult result = updateGroupInDb(db, groupUuid, groupUpdate);
    updateCachesOnGroupUpdate(result);
    dispatchAuditEventsOnGroupUpdate(result, updatedOn.get());
  }

  @VisibleForTesting
  public UpdateResult updateGroupInDb(
      ReviewDb db, AccountGroup.UUID groupUuid, InternalGroupUpdate groupUpdate)
      throws OrmException, NoSuchGroupException, IOException, ConfigInvalidException {
    UpdateResult reviewDbUpdateResult = null;
    if (!groupsMigration.disableGroupReviewDb()) {
      AccountGroup group = getExistingGroupFromReviewDb(ReviewDbUtil.unwrapDb(db), groupUuid);
      reviewDbUpdateResult = updateGroupInReviewDb(ReviewDbUtil.unwrapDb(db), group, groupUpdate);

      if (!groupsMigration.writeToNoteDb()) {
        return reviewDbUpdateResult;
      }
    }

    Optional<UpdateResult> noteDbUpdateResult =
        updateGroupInNoteDbWithRetry(groupUuid, groupUpdate);
    return noteDbUpdateResult.orElse(reviewDbUpdateResult);
  }

  private InternalGroup createGroupInReviewDb(
      ReviewDb db, InternalGroupCreation groupCreation, InternalGroupUpdate groupUpdate)
      throws OrmException {

    AccountGroupName gn = new AccountGroupName(groupCreation.getNameKey(), groupCreation.getId());
    // first insert the group name to validate that the group name hasn't
    // already been used to create another group
    db.accountGroupNames().insert(ImmutableList.of(gn));

    Timestamp createdOn = groupUpdate.getUpdatedOn().orElseGet(TimeUtil::nowTs);
    AccountGroup group = createAccountGroup(groupCreation, createdOn);
    UpdateResult updateResult = updateGroupInReviewDb(db, group, groupUpdate);
    return InternalGroup.create(
        group,
        updateResult.getAddedMembers(),
        updateResult.getAddedSubgroups(),
        updateResult.getRefState());
  }

  public static AccountGroup createAccountGroup(
      InternalGroupCreation groupCreation, InternalGroupUpdate groupUpdate) {
    Timestamp createdOn = groupUpdate.getUpdatedOn().orElseGet(TimeUtil::nowTs);
    AccountGroup group = createAccountGroup(groupCreation, createdOn);
    applyUpdate(group, groupUpdate);
    return group;
  }

  private static AccountGroup createAccountGroup(
      InternalGroupCreation groupCreation, Timestamp createdOn) {
    return new AccountGroup(
        groupCreation.getNameKey(), groupCreation.getId(), groupCreation.getGroupUUID(), createdOn);
  }

  private static void applyUpdate(AccountGroup group, InternalGroupUpdate groupUpdate) {
    groupUpdate.getName().ifPresent(group::setNameKey);
    groupUpdate.getDescription().ifPresent(d -> group.setDescription(Strings.emptyToNull(d)));
    groupUpdate.getOwnerGroupUUID().ifPresent(group::setOwnerGroupUUID);
    groupUpdate.getVisibleToAll().ifPresent(group::setVisibleToAll);
  }

  private UpdateResult updateGroupInReviewDb(
      ReviewDb db, AccountGroup group, InternalGroupUpdate groupUpdate) throws OrmException {
    AccountGroup.NameKey originalName = group.getNameKey();
    applyUpdate(group, groupUpdate);
    AccountGroup.NameKey updatedName = group.getNameKey();

    // The name must be inserted first so that we stop early for already used names.
    updateNameInReviewDb(db, group.getId(), originalName, updatedName);
    db.accountGroups().upsert(ImmutableList.of(group));

    ImmutableSet<Account.Id> originalMembers =
        Groups.getMembersFromReviewDb(db, group.getId()).collect(toImmutableSet());
    ImmutableSet<Account.Id> updatedMembers =
        ImmutableSet.copyOf(groupUpdate.getMemberModification().apply(originalMembers));
    ImmutableSet<AccountGroup.UUID> originalSubgroups =
        Groups.getSubgroupsFromReviewDb(db, group.getId()).collect(toImmutableSet());
    ImmutableSet<AccountGroup.UUID> updatedSubgroups =
        ImmutableSet.copyOf(groupUpdate.getSubgroupModification().apply(originalSubgroups));

    Set<Account.Id> addedMembers =
        addGroupMembersInReviewDb(db, group.getId(), originalMembers, updatedMembers);
    Set<Account.Id> deletedMembers =
        deleteGroupMembersInReviewDb(db, group.getId(), originalMembers, updatedMembers);
    Set<AccountGroup.UUID> addedSubgroups =
        addSubgroupsInReviewDb(db, group.getId(), originalSubgroups, updatedSubgroups);
    Set<AccountGroup.UUID> deletedSubgroups =
        deleteSubgroupsInReviewDb(db, group.getId(), originalSubgroups, updatedSubgroups);

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

  private static void updateNameInReviewDb(
      ReviewDb db,
      AccountGroup.Id groupId,
      AccountGroup.NameKey originalName,
      AccountGroup.NameKey updatedName)
      throws OrmException {
    try {
      AccountGroupName id = new AccountGroupName(updatedName, groupId);
      db.accountGroupNames().insert(ImmutableList.of(id));
    } catch (OrmException e) {
      AccountGroupName other = db.accountGroupNames().get(updatedName);
      if (other != null) {
        // If we are using this identity, don't report the exception.
        if (other.getId().equals(groupId)) {
          return;
        }
      }
      throw e;
    }
    db.accountGroupNames().deleteKeys(ImmutableList.of(originalName));
  }

  private static Set<Account.Id> addGroupMembersInReviewDb(
      ReviewDb db,
      AccountGroup.Id groupId,
      ImmutableSet<Account.Id> originalMembers,
      ImmutableSet<Account.Id> updatedMembers)
      throws OrmException {
    Set<Account.Id> accountIds = Sets.difference(updatedMembers, originalMembers);
    if (accountIds.isEmpty()) {
      return accountIds;
    }

    ImmutableSet<AccountGroupMember> newMembers = toAccountGroupMembers(groupId, accountIds);
    db.accountGroupMembers().insert(newMembers);
    return accountIds;
  }

  private static Set<Account.Id> deleteGroupMembersInReviewDb(
      ReviewDb db,
      AccountGroup.Id groupId,
      ImmutableSet<Account.Id> originalMembers,
      ImmutableSet<Account.Id> updatedMembers)
      throws OrmException {
    Set<Account.Id> accountIds = Sets.difference(originalMembers, updatedMembers);
    if (accountIds.isEmpty()) {
      return accountIds;
    }

    ImmutableSet<AccountGroupMember> membersToRemove = toAccountGroupMembers(groupId, accountIds);
    db.accountGroupMembers().delete(membersToRemove);
    return accountIds;
  }

  private static ImmutableSet<AccountGroupMember> toAccountGroupMembers(
      AccountGroup.Id groupId, Set<Account.Id> accountIds) {
    return accountIds
        .stream()
        .map(accountId -> new AccountGroupMember.Key(accountId, groupId))
        .map(AccountGroupMember::new)
        .collect(toImmutableSet());
  }

  private static Set<AccountGroup.UUID> addSubgroupsInReviewDb(
      ReviewDb db,
      AccountGroup.Id parentGroupId,
      ImmutableSet<AccountGroup.UUID> originalSubgroups,
      ImmutableSet<AccountGroup.UUID> updatedSubgroups)
      throws OrmException {
    Set<AccountGroup.UUID> subgroupUuids = Sets.difference(updatedSubgroups, originalSubgroups);
    if (subgroupUuids.isEmpty()) {
      return subgroupUuids;
    }

    ImmutableSet<AccountGroupById> newSubgroups = toAccountGroupByIds(parentGroupId, subgroupUuids);
    db.accountGroupById().insert(newSubgroups);
    return subgroupUuids;
  }

  private static Set<AccountGroup.UUID> deleteSubgroupsInReviewDb(
      ReviewDb db,
      AccountGroup.Id parentGroupId,
      ImmutableSet<AccountGroup.UUID> originalSubgroups,
      ImmutableSet<AccountGroup.UUID> updatedSubgroups)
      throws OrmException {
    Set<AccountGroup.UUID> subgroupUuids = Sets.difference(originalSubgroups, updatedSubgroups);
    if (subgroupUuids.isEmpty()) {
      return subgroupUuids;
    }

    ImmutableSet<AccountGroupById> subgroupsToRemove =
        toAccountGroupByIds(parentGroupId, subgroupUuids);
    db.accountGroupById().delete(subgroupsToRemove);
    return subgroupUuids;
  }

  private static ImmutableSet<AccountGroupById> toAccountGroupByIds(
      AccountGroup.Id parentGroupId, Set<AccountGroup.UUID> subgroupUuids) {
    return subgroupUuids
        .stream()
        .map(subgroupUuid -> new AccountGroupById.Key(parentGroupId, subgroupUuid))
        .map(AccountGroupById::new)
        .collect(toImmutableSet());
  }

  private InternalGroup createGroupInNoteDbWithRetry(
      InternalGroupCreation groupCreation, InternalGroupUpdate groupUpdate)
      throws IOException, ConfigInvalidException, OrmException {
    try {
      return retryHelper.execute(
          RetryHelper.ActionType.GROUP_UPDATE,
          () -> createGroupInNoteDb(groupCreation, groupUpdate),
          LockFailureException.class::isInstance);
    } catch (Exception e) {
      Throwables.throwIfUnchecked(e);
      Throwables.throwIfInstanceOf(e, IOException.class);
      Throwables.throwIfInstanceOf(e, ConfigInvalidException.class);
      Throwables.throwIfInstanceOf(e, OrmDuplicateKeyException.class);
      throw new IOException(e);
    }
  }

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

      GroupConfig groupConfig = GroupConfig.createForNewGroup(allUsersRepo, groupCreation);
      groupConfig.setGroupUpdate(groupUpdate, auditLogFormatter);

      commit(allUsersRepo, groupConfig, groupNameNotes);

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

  private Optional<UpdateResult> updateGroupInNoteDbWithRetry(
      AccountGroup.UUID groupUuid, InternalGroupUpdate groupUpdate)
      throws IOException, ConfigInvalidException, OrmDuplicateKeyException, NoSuchGroupException {
    try {
      return retryHelper.execute(
          RetryHelper.ActionType.GROUP_UPDATE,
          () -> updateGroupInNoteDb(groupUuid, groupUpdate),
          LockFailureException.class::isInstance);
    } catch (Exception e) {
      Throwables.throwIfUnchecked(e);
      Throwables.throwIfInstanceOf(e, IOException.class);
      Throwables.throwIfInstanceOf(e, ConfigInvalidException.class);
      Throwables.throwIfInstanceOf(e, OrmDuplicateKeyException.class);
      Throwables.throwIfInstanceOf(e, NoSuchGroupException.class);
      throw new IOException(e);
    }
  }

  private Optional<UpdateResult> updateGroupInNoteDb(
      AccountGroup.UUID groupUuid, InternalGroupUpdate groupUpdate)
      throws IOException, ConfigInvalidException, OrmDuplicateKeyException, NoSuchGroupException {
    try (Repository allUsersRepo = repoManager.openRepository(allUsersName)) {
      GroupConfig groupConfig = GroupConfig.loadForGroup(allUsersRepo, groupUuid);
      groupConfig.setGroupUpdate(groupUpdate, auditLogFormatter);
      if (!groupConfig.getLoadedGroup().isPresent()) {
        if (groupsMigration.readFromNoteDb()) {
          throw new NoSuchGroupException(groupUuid);
        }
        return Optional.empty();
      }

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

      commit(allUsersRepo, groupConfig, groupNameNotes);

      InternalGroup updatedGroup =
          groupConfig
              .getLoadedGroup()
              .orElseThrow(
                  () -> new IllegalStateException("Updated group wasn't automatically loaded"));
      return Optional.of(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)
            .setRefState(updatedGroup.getRefState());
    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 != null ? currentUser.state() : null);
  }

  private void updateCachesOnGroupCreation(InternalGroup createdGroup) throws IOException {
    indexer.get().index(createdGroup.getGroupUUID());
    for (Account.Id modifiedMember : createdGroup.getMembers()) {
      groupIncludeCache.evictGroupsWithMember(modifiedMember);
    }
    for (AccountGroup.UUID modifiedSubgroup : createdGroup.getSubgroups()) {
      groupIncludeCache.evictParentGroupsOf(modifiedSubgroup);
    }
  }

  private void updateCachesOnGroupUpdate(UpdateResult result) throws IOException {
    if (result.getPreviousGroupName().isPresent()) {
      AccountGroup.NameKey previousName = result.getPreviousGroupName().get();
      groupCache.evict(previousName);

      // TODO(aliceks): After switching to NoteDb, consider to use a BatchRefUpdate.
      @SuppressWarnings("unused")
      Future<?> possiblyIgnoredError =
          renameGroupOpFactory
              .create(
                  authorIdent,
                  result.getGroupUuid(),
                  previousName.get(),
                  result.getGroupName().get())
              .start(0, TimeUnit.MILLISECONDS);
    }
    groupCache.evict(result.getGroupUuid());
    groupCache.evict(result.getGroupId());
    groupCache.evict(result.getGroupName());
    indexer.get().index(result.getGroupUuid());

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

  private void dispatchAuditEventsOnGroupCreation(InternalGroup createdGroup) {
    if (currentUser == null) {
      return;
    }

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

  private void dispatchAuditEventsOnGroupUpdate(UpdateResult result, Timestamp updatedOn) {
    if (currentUser == null) {
      return;
    }

    if (!result.getAddedMembers().isEmpty()) {
      auditService.dispatchAddMembers(
          currentUser.getAccountId(), result.getGroupUuid(), result.getAddedMembers(), updatedOn);
    }
    if (!result.getDeletedMembers().isEmpty()) {
      auditService.dispatchDeleteMembers(
          currentUser.getAccountId(), result.getGroupUuid(), result.getDeletedMembers(), updatedOn);
    }
    if (!result.getAddedSubgroups().isEmpty()) {
      auditService.dispatchAddSubgroups(
          currentUser.getAccountId(), result.getGroupUuid(), result.getAddedSubgroups(), updatedOn);
    }
    if (!result.getDeletedSubgroups().isEmpty()) {
      auditService.dispatchDeleteSubgroups(
          currentUser.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();

    @Nullable
    public abstract ObjectId getRefState();

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

      public abstract Builder setRefState(ObjectId refState);

      abstract UpdateResult build();
    }
  }
}
