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

import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.reviewdb.client.RefNames.REFS_USERS;
import static java.util.stream.Collectors.toSet;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;
import com.google.common.collect.Sets;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.index.RefState;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.account.AccountCache;
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.git.GitRepositoryManager;
import com.google.gerrit.server.index.account.AccountIndexer;
import com.google.gerrit.server.index.group.GroupIndexer;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.RefPatternMatcher;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;

/**
 * Saves the states of given projects and resets the project states on close.
 *
 * <p>Saving the project states is done by saving the states of all refs in the project. On close
 * those refs are reset to the saved states. Refs that were newly created are deleted.
 *
 * <p>By providing ref patterns per project it can be controlled which refs should be reset on
 * close.
 *
 * <p>If resetting touches {@code refs/meta/config} branches the corresponding projects are evicted
 * from the project cache.
 *
 * <p>If resetting touches user branches or the {@code refs/meta/external-ids} branch the
 * corresponding accounts are evicted from the account cache and also if needed from the cache in
 * {@link AccountCreator}.
 *
 * <p>At the moment this class has the following limitations:
 *
 * <ul>
 *   <li>Resetting group branches doesn't evict the corresponding groups from the group cache.
 *   <li>Changes are not reindexed if change meta refs are reset.
 *   <li>Changes are not reindexed if starred-changes refs in All-Users are reset.
 *   <li>If accounts are deleted changes may still refer to these accounts (e.g. as reviewers).
 * </ul>
 *
 * Primarily this class is intended to reset the states of the All-Projects and All-Users projects
 * after each test. These projects rarely contain changes and it's currently not a problem if these
 * changes get stale. For creating changes each test gets a brand new project. Since this project is
 * not used outside of the test method that creates it, it doesn't need to be reset.
 */
public class ProjectResetter implements AutoCloseable {
  public static class Builder {
    public interface Factory {
      Builder builder();
    }

    private final GitRepositoryManager repoManager;
    private final AllUsersName allUsersName;
    @Nullable private final AccountCreator accountCreator;
    @Nullable private final AccountCache accountCache;
    @Nullable private final AccountIndexer accountIndexer;
    @Nullable private final GroupCache groupCache;
    @Nullable private final GroupIncludeCache groupIncludeCache;
    @Nullable private final GroupIndexer groupIndexer;
    @Nullable private final ProjectCache projectCache;

    @Inject
    public Builder(
        GitRepositoryManager repoManager,
        AllUsersName allUsersName,
        @Nullable AccountCreator accountCreator,
        @Nullable AccountCache accountCache,
        @Nullable AccountIndexer accountIndexer,
        @Nullable GroupCache groupCache,
        @Nullable GroupIncludeCache groupIncludeCache,
        @Nullable GroupIndexer groupIndexer,
        @Nullable ProjectCache projectCache) {
      this.repoManager = repoManager;
      this.allUsersName = allUsersName;
      this.accountCreator = accountCreator;
      this.accountCache = accountCache;
      this.accountIndexer = accountIndexer;
      this.groupCache = groupCache;
      this.groupIncludeCache = groupIncludeCache;
      this.groupIndexer = groupIndexer;
      this.projectCache = projectCache;
    }

    public ProjectResetter build(ProjectResetter.Config input) throws IOException {
      return new ProjectResetter(
          repoManager,
          allUsersName,
          accountCreator,
          accountCache,
          accountIndexer,
          groupCache,
          groupIncludeCache,
          groupIndexer,
          projectCache,
          input.refsByProject);
    }
  }

  public static class Config {
    private final Multimap<Project.NameKey, String> refsByProject;

    public Config() {
      this.refsByProject = MultimapBuilder.hashKeys().arrayListValues().build();
    }

    public Config reset(Project.NameKey project, String... refPatterns) {
      List<String> refPatternList = Arrays.asList(refPatterns);
      if (refPatternList.isEmpty()) {
        refPatternList = ImmutableList.of(RefNames.REFS + "*");
      }
      refsByProject.putAll(project, refPatternList);
      return this;
    }
  }

  @Inject private GitRepositoryManager repoManager;
  @Inject private AllUsersName allUsersName;
  @Inject @Nullable private AccountCreator accountCreator;
  @Inject @Nullable private AccountCache accountCache;
  @Inject @Nullable private GroupCache groupCache;
  @Inject @Nullable private GroupIncludeCache groupIncludeCache;
  @Inject @Nullable private GroupIndexer groupIndexer;
  @Inject @Nullable private AccountIndexer accountIndexer;
  @Inject @Nullable private ProjectCache projectCache;

  private final Multimap<Project.NameKey, String> refsPatternByProject;

  // State to which to reset to.
  private final Multimap<Project.NameKey, RefState> savedRefStatesByProject;

  // Results of the resetting
  private Multimap<Project.NameKey, String> keptRefsByProject;
  private Multimap<Project.NameKey, String> restoredRefsByProject;
  private Multimap<Project.NameKey, String> deletedRefsByProject;

  private ProjectResetter(
      GitRepositoryManager repoManager,
      AllUsersName allUsersName,
      @Nullable AccountCreator accountCreator,
      @Nullable AccountCache accountCache,
      @Nullable AccountIndexer accountIndexer,
      @Nullable GroupCache groupCache,
      @Nullable GroupIncludeCache groupIncludeCache,
      @Nullable GroupIndexer groupIndexer,
      @Nullable ProjectCache projectCache,
      Multimap<Project.NameKey, String> refPatternByProject)
      throws IOException {
    this.repoManager = repoManager;
    this.allUsersName = allUsersName;
    this.accountCreator = accountCreator;
    this.accountCache = accountCache;
    this.accountIndexer = accountIndexer;
    this.groupCache = groupCache;
    this.groupIndexer = groupIndexer;
    this.groupIncludeCache = groupIncludeCache;
    this.projectCache = projectCache;
    this.refsPatternByProject = refPatternByProject;
    this.savedRefStatesByProject = readRefStates();
  }

  @Override
  public void close() throws Exception {
    keptRefsByProject = MultimapBuilder.hashKeys().arrayListValues().build();
    restoredRefsByProject = MultimapBuilder.hashKeys().arrayListValues().build();
    deletedRefsByProject = MultimapBuilder.hashKeys().arrayListValues().build();

    restoreRefs();
    deleteNewlyCreatedRefs();
    evictCachesAndReindex();
  }

  /** Read the states of all matching refs. */
  private Multimap<Project.NameKey, RefState> readRefStates() throws IOException {
    Multimap<Project.NameKey, RefState> refStatesByProject =
        MultimapBuilder.hashKeys().arrayListValues().build();
    for (Map.Entry<Project.NameKey, Collection<String>> e :
        refsPatternByProject.asMap().entrySet()) {
      try (Repository repo = repoManager.openRepository(e.getKey())) {
        Collection<Ref> refs = repo.getAllRefs().values();
        for (String refPattern : e.getValue()) {
          RefPatternMatcher matcher = RefPatternMatcher.getMatcher(refPattern);
          for (Ref ref : refs) {
            if (matcher.match(ref.getName(), null)) {
              refStatesByProject.put(e.getKey(), RefState.create(ref.getName(), ref.getObjectId()));
            }
          }
        }
      }
    }
    return refStatesByProject;
  }

  private void restoreRefs() throws IOException {
    for (Map.Entry<Project.NameKey, Collection<RefState>> e :
        savedRefStatesByProject.asMap().entrySet()) {
      try (Repository repo = repoManager.openRepository(e.getKey())) {
        for (RefState refState : e.getValue()) {
          if (refState.match(repo)) {
            keptRefsByProject.put(e.getKey(), refState.ref());
            continue;
          }
          Ref ref = repo.exactRef(refState.ref());
          RefUpdate updateRef = repo.updateRef(refState.ref());
          updateRef.setExpectedOldObjectId(ref != null ? ref.getObjectId() : ObjectId.zeroId());
          updateRef.setNewObjectId(refState.id());
          updateRef.setForceUpdate(true);
          RefUpdate.Result result = updateRef.update();
          checkState(
              result == RefUpdate.Result.FORCED || result == RefUpdate.Result.NEW,
              "resetting branch %s in %s failed",
              refState.ref(),
              e.getKey());
          restoredRefsByProject.put(e.getKey(), refState.ref());
        }
      }
    }
  }

  private void deleteNewlyCreatedRefs() throws IOException {
    for (Map.Entry<Project.NameKey, Collection<String>> e :
        refsPatternByProject.asMap().entrySet()) {
      try (Repository repo = repoManager.openRepository(e.getKey())) {
        Collection<Ref> nonRestoredRefs =
            repo.getAllRefs()
                .values()
                .stream()
                .filter(
                    r ->
                        !keptRefsByProject.containsEntry(e.getKey(), r.getName())
                            && !restoredRefsByProject.containsEntry(e.getKey(), r.getName()))
                .collect(toSet());
        for (String refPattern : e.getValue()) {
          RefPatternMatcher matcher = RefPatternMatcher.getMatcher(refPattern);
          for (Ref ref : nonRestoredRefs) {
            if (matcher.match(ref.getName(), null)
                && !deletedRefsByProject.containsEntry(e.getKey(), ref.getName())) {
              RefUpdate updateRef = repo.updateRef(ref.getName());
              updateRef.setExpectedOldObjectId(ref.getObjectId());
              updateRef.setNewObjectId(ObjectId.zeroId());
              updateRef.setForceUpdate(true);
              RefUpdate.Result result = updateRef.delete();
              checkState(
                  result == RefUpdate.Result.FORCED,
                  "deleting branch %s in %s failed",
                  ref.getName(),
                  e.getKey());
              deletedRefsByProject.put(e.getKey(), ref.getName());
            }
          }
        }
      }
    }
  }

  private void evictCachesAndReindex() throws IOException {
    evictAndReindexProjects();
    evictAndReindexAccounts();
    evictAndReindexGroups();

    // TODO(ekempin): Reindex changes if starred-changes refs in All-Users were modified.
  }

  /** Evict projects for which the config was changed. */
  private void evictAndReindexProjects() throws IOException {
    if (projectCache == null) {
      return;
    }

    for (Project.NameKey project :
        Sets.union(
            projectsWithConfigChanges(restoredRefsByProject),
            projectsWithConfigChanges(deletedRefsByProject))) {
      projectCache.evict(project);
    }
  }

  private Set<Project.NameKey> projectsWithConfigChanges(
      Multimap<Project.NameKey, String> projects) {
    return projects
        .entries()
        .stream()
        .filter(e -> e.getValue().equals(RefNames.REFS_CONFIG))
        .map(Map.Entry::getKey)
        .collect(toSet());
  }

  /** Evict accounts that were modified. */
  private void evictAndReindexAccounts() throws IOException {
    Set<Account.Id> deletedAccounts = accountIds(deletedRefsByProject.get(allUsersName));
    if (accountCreator != null) {
      accountCreator.evict(deletedAccounts);
    }
    if (accountCache != null || accountIndexer != null) {
      Set<Account.Id> modifiedAccounts =
          new HashSet<>(accountIds(restoredRefsByProject.get(allUsersName)));

      if (restoredRefsByProject.get(allUsersName).contains(RefNames.REFS_EXTERNAL_IDS)
          || deletedRefsByProject.get(allUsersName).contains(RefNames.REFS_EXTERNAL_IDS)) {
        // The external IDs have been modified but we don't know which accounts were affected.
        // Make sure all accounts are evicted and reindexed.
        try (Repository repo = repoManager.openRepository(allUsersName)) {
          for (Account.Id id :
              accountIds(repo.getAllRefs().values().stream().map(Ref::getName).collect(toSet()))) {
            evictAndReindexAccount(id);
          }
        }

        // Remove deleted accounts from the cache and index.
        for (Account.Id id : deletedAccounts) {
          evictAndReindexAccount(id);
        }
      } else {
        // Evict and reindex all modified and deleted accounts.
        for (Account.Id id : Sets.union(modifiedAccounts, deletedAccounts)) {
          evictAndReindexAccount(id);
        }
      }
    }
  }

  /** Evict groups that were modified. */
  private void evictAndReindexGroups() throws IOException {
    if (groupCache != null || groupIndexer != null) {
      Set<AccountGroup.UUID> modifiedGroups =
          new HashSet<>(groupUUIDs(restoredRefsByProject.get(allUsersName)));
      Set<AccountGroup.UUID> deletedGroups =
          new HashSet<>(groupUUIDs(deletedRefsByProject.get(allUsersName)));

      // Evict and reindex all modified and deleted groups.
      for (AccountGroup.UUID uuid : Sets.union(modifiedGroups, deletedGroups)) {
        evictAndReindexGroup(uuid);
      }
    }
  }

  private void evictAndReindexAccount(Account.Id accountId) throws IOException {
    if (accountCache != null) {
      accountCache.evict(accountId);
    }
    if (groupIncludeCache != null) {
      groupIncludeCache.evictGroupsWithMember(accountId);
    }
    if (accountIndexer != null) {
      accountIndexer.index(accountId);
    }
  }

  private void evictAndReindexGroup(AccountGroup.UUID uuid) throws IOException {
    if (groupCache != null) {
      groupCache.evict(uuid);
    }

    if (groupIncludeCache != null) {
      groupIncludeCache.evictParentGroupsOf(uuid);
    }

    if (groupIndexer != null) {
      groupIndexer.index(uuid);
    }
  }

  private Set<Account.Id> accountIds(Collection<String> refs) {
    return refs.stream()
        .filter(r -> r.startsWith(REFS_USERS))
        .map(Account.Id::fromRef)
        .filter(Objects::nonNull)
        .collect(toSet());
  }

  private Set<AccountGroup.UUID> groupUUIDs(Collection<String> refs) {
    return refs.stream()
        .filter(RefNames::isRefsGroups)
        .map(AccountGroup.UUID::fromRef)
        .filter(Objects::nonNull)
        .collect(toSet());
  }
}
