// Copyright (C) 2013 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.testing;

import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.ACCOUNTS_UPDATE;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.BAN_COMMIT;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.BRANCH_MODIFICATION;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.CHANGE_MODIFICATION;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.DIRECT_PUSH;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.GPG_KEYS_MODIFICATION;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.GROUPS_UPDATE;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.HEAD_MODIFICATION;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.INIT_REPO;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.MERGE_CHANGE;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.OFFLINE_OPERATION;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.PLUGIN;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.REPO_SEQ;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.TAG_MODIFICATION;
import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.VERSIONED_META_DATA_CHANGE;
import static java.util.stream.Collectors.toList;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.Project.NameKey;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.gpg.PublicKeyStore;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.RepositoryCaseMismatchException;
import com.google.gerrit.server.update.context.RefUpdateContext;
import com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType;
import com.google.inject.Inject;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NavigableSet;
import java.util.Optional;
import java.util.function.Predicate;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase;
import org.eclipse.jgit.internal.storage.dfs.DfsReftableBatchRefUpdate;
import org.eclipse.jgit.internal.storage.dfs.DfsRepository;
import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.ReceiveCommand;

/** Repository manager that uses in-memory repositories. */
public class InMemoryRepositoryManager implements GitRepositoryManager {
  public static InMemoryRepository newRepository(Project.NameKey name) {
    return new Repo(name);
  }

  public static class Description extends DfsRepositoryDescription {
    private final Project.NameKey name;

    private Description(Project.NameKey name) {
      super(name.get());
      this.name = name;
    }

    public Project.NameKey getProject() {
      return name;
    }
  }

  public static class Repo extends InMemoryRepository {
    private String description;

    private Repo(Project.NameKey name) {
      super(new Description(name));
      setPerformsAtomicTransactions(true);
    }

    /** Validates that a given ref is updated within the expected context. */
    private static class RefUpdateContextValidator {
      /**
       * A configured singleton for ref context validation.
       *
       * <p>Each ref must match no more than 1 special ref from the list below. If ref is not
       * matched to any special ref predicate, then it is checked against the standard rules - check
       * the code of the {@link #validateRefUpdateContext} for details.
       */
      public static final RefUpdateContextValidator INSTANCE =
          new RefUpdateContextValidator()
              .addSpecialRef(RefNames::isSequenceRef, REPO_SEQ)
              .addSpecialRef(RefNames.HEAD::equals, HEAD_MODIFICATION)
              .addSpecialRef(RefNames::isRefsChanges, CHANGE_MODIFICATION, MERGE_CHANGE)
              .addSpecialRef(RefNames::isAutoMergeRef, CHANGE_MODIFICATION)
              .addSpecialRef(RefNames::isRefsEdit, CHANGE_MODIFICATION, MERGE_CHANGE)
              .addSpecialRef(RefNames::isTagRef, TAG_MODIFICATION)
              .addSpecialRef(RefNames::isRejectCommitsRef, BAN_COMMIT)
              .addSpecialRef(
                  name -> RefNames.isRefsUsers(name) && !RefNames.isRefsEdit(name),
                  VERSIONED_META_DATA_CHANGE,
                  ACCOUNTS_UPDATE,
                  MERGE_CHANGE)
              .addSpecialRef(
                  RefNames::isConfigRef,
                  VERSIONED_META_DATA_CHANGE,
                  BRANCH_MODIFICATION,
                  MERGE_CHANGE)
              .addSpecialRef(RefNames::isExternalIdRef, VERSIONED_META_DATA_CHANGE, ACCOUNTS_UPDATE)
              .addSpecialRef(PublicKeyStore.REFS_GPG_KEYS::equals, GPG_KEYS_MODIFICATION)
              .addSpecialRef(RefNames::isRefsDraftsComments, CHANGE_MODIFICATION)
              .addSpecialRef(RefNames::isRefsStarredChanges, CHANGE_MODIFICATION)
              // A user can create a change for updating a group and then merge it.
              // The GroupsIT#pushToGroupBranchForReviewForNonAllUsersRepoAndSubmit test verifies
              // this scenario.
              .addSpecialRef(RefNames::isGroupRef, GROUPS_UPDATE, MERGE_CHANGE);

      private List<Entry<Predicate<String>, ImmutableList<RefUpdateType>>> specialRefs =
          new ArrayList<>();

      private RefUpdateContextValidator() {}

      public void validateRefUpdateContext(ReceiveCommand cmd) {
        String refName = cmd.getRefName();

        if (RefUpdateContextCollector.enabled()) {
          RefUpdateContextCollector.register(refName, RefUpdateContext.getOpenedContexts());
        }
        if (TestActionRefUpdateContext.isOpen()
            || RefUpdateContext.hasOpen(OFFLINE_OPERATION)
            || RefUpdateContext.hasOpen(INIT_REPO)
            || RefUpdateContext.hasOpen(DIRECT_PUSH)) {
          // The action can touch any refs in these contexts.
          return;
        }

        Optional<ImmutableList<RefUpdateType>> allowedRefUpdateTypes =
            RefUpdateContextValidator.INSTANCE.getAllowedRefUpdateTypes(refName);

        if (allowedRefUpdateTypes.isPresent()) {
          checkState(
              allowedRefUpdateTypes.get().stream().anyMatch(RefUpdateContext::hasOpen)
                  || isTestRepoCall(),
              "Special ref '%s' is updated outside of the expected operation. Wrap code in the correct RefUpdateContext or fix allowed update types",
              refName);
          return;
        }
        // It is not one of the special ref - update is possible only within specific contexts.
        checkState(
            RefUpdateContext.hasOpen(MERGE_CHANGE)
                || RefUpdateContext.hasOpen(RefUpdateType.BRANCH_MODIFICATION)
                || RefUpdateContext.hasOpen(RefUpdateType.UPDATE_SUPERPROJECT)
                // Plugin can update any ref
                || RefUpdateContext.hasOpen(PLUGIN)
                || isTestRepoCall(),
            "Ordinary ref '%s' is updated outside of the expected operation. Wrap code in the correct RefUpdateContext or add the ref as a special ref.",
            refName);
      }

      private RefUpdateContextValidator addSpecialRef(
          Predicate<String> refNamePredicate, RefUpdateType... validRefUpdateTypes) {
        specialRefs.add(
            new SimpleImmutableEntry<>(
                refNamePredicate, ImmutableList.copyOf(validRefUpdateTypes)));
        return this;
      }

      private Optional<ImmutableList<RefUpdateType>> getAllowedRefUpdateTypes(String refName) {
        List<ImmutableList<RefUpdateType>> allowedTypes =
            specialRefs.stream()
                .filter(entry -> entry.getKey().test(refName))
                .map(Entry::getValue)
                .collect(toList());
        checkState(
            allowedTypes.size() <= 1,
            "refName matches more than 1 predicate. Please fix the specialRefs list, so each reference has no more than one match.");
        if (allowedTypes.size() == 0) {
          return Optional.empty();
        }
        return Optional.of(allowedTypes.get(0));
      }

      /**
       * Returns true if a ref is updated using one of the method in {@link
       * org.eclipse.jgit.junit.TestRepository}.
       *
       * <p>The {@link org.eclipse.jgit.junit.TestRepository} used only in tests and allows to
       * change refs directly. Wrapping each usage in a test context requires a lot of modification,
       * so instead we allow any ref updates, which are made using through this class.
       */
      private boolean isTestRepoCall() {
        return Arrays.stream(Thread.currentThread().getStackTrace())
            .anyMatch(elem -> elem.getClassName().equals("org.eclipse.jgit.junit.TestRepository"));
      }
    }

    @Override
    protected MemRefDatabase createRefDatabase() {
      return new MemRefDatabase() {
        @Override
        public BatchRefUpdate newBatchUpdate() {
          DfsObjDatabase odb = getRepository().getObjectDatabase();
          return new DfsReftableBatchRefUpdate(this, odb) {
            @Override
            public void execute(RevWalk rw, ProgressMonitor pm, List<String> options) {
              getCommands().stream()
                  .forEach(RefUpdateContextValidator.INSTANCE::validateRefUpdateContext);
              super.execute(rw, pm, options);
            }
          };
        }
      };
    }

    @Override
    public Description getDescription() {
      return (Description) super.getDescription();
    }

    @Override
    public String getGitwebDescription() {
      return description;
    }

    @Override
    public void setGitwebDescription(String d) {
      description = d;
    }
  }

  private final Map<String, Repo> repos;

  @Inject
  public InMemoryRepositoryManager() {
    this.repos = new HashMap<>();
  }

  @Override
  public synchronized Status getRepositoryStatus(NameKey name) {
    try {
      get(name);
      return Status.ACTIVE;
    } catch (RepositoryNotFoundException e) {
      return Status.NON_EXISTENT;
    }
  }

  @Override
  public synchronized Repo openRepository(Project.NameKey name) throws RepositoryNotFoundException {
    return get(name);
  }

  @Override
  public synchronized Repo createRepository(Project.NameKey name)
      throws RepositoryCaseMismatchException, RepositoryNotFoundException {
    Repo repo;
    try {
      repo = get(name);
      if (!repo.getDescription().getRepositoryName().equals(name.get())) {
        throw new RepositoryCaseMismatchException(name);
      }
    } catch (RepositoryNotFoundException e) {
      repo = new Repo(name);
      repos.put(normalize(name), repo);
    }
    return repo;
  }

  @Override
  public synchronized NavigableSet<Project.NameKey> list() {
    NavigableSet<Project.NameKey> names = Sets.newTreeSet();
    for (DfsRepository repo : repos.values()) {
      names.add(Project.nameKey(repo.getDescription().getRepositoryName()));
    }
    return Collections.unmodifiableNavigableSet(names);
  }

  public synchronized void deleteRepository(Project.NameKey name) {
    repos.remove(normalize(name));
  }

  private synchronized Repo get(Project.NameKey name) throws RepositoryNotFoundException {
    Repo repo = repos.get(normalize(name));
    if (repo != null) {
      repo.incrementOpen();
      return repo;
    }
    throw new RepositoryNotFoundException(name.get());
  }

  private static String normalize(Project.NameKey name) {
    return name.get().toLowerCase(Locale.US);
  }
}
