// 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, MERGE_CHANGE)
              .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 {
      @SuppressWarnings("unused")
      var unused = 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);
  }
}
