// Copyright (C) 2020 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.testsuite.change;

import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Streams;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.change.ChangeFinder;
import com.google.gerrit.server.change.ChangeInserter;
import com.google.gerrit.server.change.PatchSetInserter;
import com.google.gerrit.server.edit.tree.TreeCreator;
import com.google.gerrit.server.edit.tree.TreeModification;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.Sequences;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.UpdateException;
import com.google.gerrit.server.util.CommitMessageUtil;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.Inject;
import java.io.IOException;
import java.time.Instant;
import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.merge.MergeStrategy;
import org.eclipse.jgit.merge.Merger;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.ChangeIdUtil;

/**
 * The implementation of {@link ChangeOperations}.
 *
 * <p>There is only one implementation of {@link ChangeOperations}. Nevertheless, we keep the
 * separation between interface and implementation to enhance clarity.
 */
public class ChangeOperationsImpl implements ChangeOperations {
  private final Sequences seq;
  private final ChangeInserter.Factory changeInserterFactory;
  private final PatchSetInserter.Factory patchsetInserterFactory;
  private final GitRepositoryManager repositoryManager;
  private final AccountResolver resolver;
  private final IdentifiedUser.GenericFactory userFactory;
  private final PersonIdent serverIdent;
  private final BatchUpdate.Factory batchUpdateFactory;
  private final ProjectCache projectCache;
  private final ChangeFinder changeFinder;
  private final PerPatchsetOperationsImpl.Factory perPatchsetOperationsFactory;
  private final PerCommentOperationsImpl.Factory perCommentOperationsFactory;
  private final PerDraftCommentOperationsImpl.Factory perDraftCommentOperationsFactory;
  private final PerRobotCommentOperationsImpl.Factory perRobotCommentOperationsFactory;

  @Inject
  public ChangeOperationsImpl(
      Sequences seq,
      ChangeInserter.Factory changeInserterFactory,
      PatchSetInserter.Factory patchsetInserterFactory,
      GitRepositoryManager repositoryManager,
      AccountResolver resolver,
      IdentifiedUser.GenericFactory userFactory,
      @GerritPersonIdent PersonIdent serverIdent,
      BatchUpdate.Factory batchUpdateFactory,
      ProjectCache projectCache,
      ChangeFinder changeFinder,
      PerPatchsetOperationsImpl.Factory perPatchsetOperationsFactory,
      PerCommentOperationsImpl.Factory perCommentOperationsFactory,
      PerDraftCommentOperationsImpl.Factory perDraftCommentOperationsFactory,
      PerRobotCommentOperationsImpl.Factory perRobotCommentOperationsFactory) {
    this.seq = seq;
    this.changeInserterFactory = changeInserterFactory;
    this.patchsetInserterFactory = patchsetInserterFactory;
    this.repositoryManager = repositoryManager;
    this.resolver = resolver;
    this.userFactory = userFactory;
    this.serverIdent = serverIdent;
    this.batchUpdateFactory = batchUpdateFactory;
    this.projectCache = projectCache;
    this.changeFinder = changeFinder;
    this.perPatchsetOperationsFactory = perPatchsetOperationsFactory;
    this.perCommentOperationsFactory = perCommentOperationsFactory;
    this.perDraftCommentOperationsFactory = perDraftCommentOperationsFactory;
    this.perRobotCommentOperationsFactory = perRobotCommentOperationsFactory;
  }

  @Override
  public PerChangeOperations change(Change.Id changeId) {
    return new PerChangeOperationsImpl(changeId);
  }

  @Override
  public TestChangeCreation.Builder newChange() {
    return TestChangeCreation.builder(this::createChange);
  }

  private Change.Id createChange(TestChangeCreation changeCreation) throws Exception {
    Change.Id changeId = Change.id(seq.nextChangeId());
    Project.NameKey project = getTargetProject(changeCreation);

    try (Repository repository = repositoryManager.openRepository(project);
        ObjectInserter objectInserter = repository.newObjectInserter();
        RevWalk revWalk = new RevWalk(objectInserter.newReader())) {
      Instant now = TimeUtil.now();
      IdentifiedUser changeOwner = getChangeOwner(changeCreation);
      PersonIdent authorAndCommitter = changeOwner.newCommitterIdent(now, serverIdent.getZoneId());
      ObjectId commitId =
          createCommit(repository, revWalk, objectInserter, changeCreation, authorAndCommitter);

      String refName = RefNames.fullName(changeCreation.branch());
      ChangeInserter inserter = getChangeInserter(changeId, refName, commitId);
      changeCreation.topic().ifPresent(t -> inserter.setTopic(t));
      inserter.setApprovals(changeCreation.approvals());

      try (BatchUpdate batchUpdate = batchUpdateFactory.create(project, changeOwner, now)) {
        batchUpdate.setRepository(repository, revWalk, objectInserter);
        batchUpdate.insertChange(inserter);
        batchUpdate.execute();
      }
      return changeId;
    }
  }

  private Project.NameKey getTargetProject(TestChangeCreation changeCreation) {
    if (changeCreation.project().isPresent()) {
      return changeCreation.project().get();
    }

    return getArbitraryProject();
  }

  private Project.NameKey getArbitraryProject() {
    Project.NameKey allProjectsName = projectCache.getAllProjects().getNameKey();
    Project.NameKey allUsersName = projectCache.getAllUsers().getNameKey();
    Optional<Project.NameKey> arbitraryProject =
        projectCache.all().stream()
            .filter(
                name ->
                    !Objects.equals(name, allProjectsName) && !Objects.equals(name, allUsersName))
            .findFirst();
    checkState(
        arbitraryProject.isPresent(),
        "At least one repository must be available on the Gerrit server");
    return arbitraryProject.get();
  }

  private IdentifiedUser getChangeOwner(TestChangeCreation changeCreation)
      throws IOException, ConfigInvalidException {
    if (changeCreation.owner().isPresent()) {
      return userFactory.create(changeCreation.owner().get());
    }

    return getArbitraryUser();
  }

  private IdentifiedUser getArbitraryUser() throws ConfigInvalidException, IOException {
    ImmutableSet<Account.Id> foundAccounts = resolver.resolveIgnoreVisibility("").asIdSet();
    checkState(
        !foundAccounts.isEmpty(),
        "At least one user account must be available on the Gerrit server");
    return userFactory.create(foundAccounts.iterator().next());
  }

  private ObjectId createCommit(
      Repository repository,
      RevWalk revWalk,
      ObjectInserter objectInserter,
      TestChangeCreation changeCreation,
      PersonIdent authorAndCommitter)
      throws IOException, BadRequestException {
    ImmutableList<ObjectId> parentCommits = getParentCommits(repository, revWalk, changeCreation);
    TreeCreator treeCreator =
        getTreeCreator(objectInserter, parentCommits, changeCreation.mergeStrategy());
    ObjectId tree = createNewTree(repository, treeCreator, changeCreation.treeModifications());
    String commitMessage = correctCommitMessage(changeCreation.commitMessage());
    return createCommit(
        objectInserter, tree, parentCommits, authorAndCommitter, authorAndCommitter, commitMessage);
  }

  private ImmutableList<ObjectId> getParentCommits(
      Repository repository, RevWalk revWalk, TestChangeCreation changeCreation) {

    return changeCreation
        .parents()
        .map(parents -> resolveParents(repository, revWalk, parents))
        .orElseGet(() -> asImmutableList(getTip(repository, changeCreation.branch())));
  }

  private ImmutableList<ObjectId> resolveParents(
      Repository repository, RevWalk revWalk, ImmutableList<TestCommitIdentifier> parents) {
    return parents.stream()
        .map(parent -> resolveCommit(repository, revWalk, parent))
        .collect(toImmutableList());
  }

  private ObjectId resolveCommit(
      Repository repository, RevWalk revWalk, TestCommitIdentifier parentCommit) {
    switch (parentCommit.getKind()) {
      case BRANCH:
        return resolveBranchTip(repository, parentCommit.branch());
      case CHANGE_ID:
        return resolveChange(parentCommit.changeId());
      case COMMIT_SHA_1:
        return resolveCommitFromSha1(revWalk, parentCommit.commitSha1());
      case PATCHSET_ID:
        return resolvePatchset(parentCommit.patchsetId());
      default:
        throw new IllegalStateException(
            String.format("No parent behavior implemented for %s.", parentCommit.getKind()));
    }
  }

  private static ObjectId resolveBranchTip(Repository repository, String branchName) {
    return getTip(repository, branchName)
        .orElseThrow(
            () ->
                new IllegalStateException(
                    String.format(
                        "Tip of branch %s not found and hence can't be used as parent.",
                        branchName)));
  }

  private static Optional<ObjectId> getTip(Repository repository, String branch) {
    try {
      Optional<Ref> ref = Optional.ofNullable(repository.findRef(branch));
      return ref.map(Ref::getObjectId);
    } catch (IOException e) {
      throw new StorageException(e);
    }
  }

  private ObjectId resolveChange(Change.Id changeId) {
    Optional<ChangeNotes> changeNotes = changeFinder.findOne(changeId);
    return changeNotes
        .map(ChangeNotes::getCurrentPatchSet)
        .map(PatchSet::commitId)
        .orElseThrow(
            () ->
                new IllegalStateException(
                    String.format(
                        "Change %s not found and hence can't be used as parent.", changeId)));
  }

  private static RevCommit resolveCommitFromSha1(RevWalk revWalk, ObjectId commitSha1) {
    try {
      return revWalk.parseCommit(commitSha1);
    } catch (Exception e) {
      throw new IllegalStateException(
          String.format("Commit %s not found and hence can't be used as parent/base.", commitSha1),
          e);
    }
  }

  private ObjectId resolvePatchset(PatchSet.Id patchsetId) {
    Optional<ChangeNotes> changeNotes = changeFinder.findOne(patchsetId.changeId());
    return changeNotes
        .map(ChangeNotes::getPatchSets)
        .map(patchsets -> patchsets.get(patchsetId))
        .map(PatchSet::commitId)
        .orElseThrow(
            () ->
                new IllegalStateException(
                    String.format(
                        "Patchset %s not found and hence can't be used as parent.", patchsetId)));
  }

  private static <T> ImmutableList<T> asImmutableList(Optional<T> value) {
    return Streams.stream(value).collect(toImmutableList());
  }

  private static TreeCreator getTreeCreator(
      RevWalk revWalk, ObjectId customBaseCommit, ImmutableList<ObjectId> parentCommits) {
    RevCommit commit = resolveCommitFromSha1(revWalk, customBaseCommit);
    // Use actual parents; relevant for example when a file is restored (->
    // RestoreFileModification).
    return TreeCreator.basedOnTree(commit.getTree(), parentCommits);
  }

  private static TreeCreator getTreeCreator(
      ObjectInserter objectInserter,
      ImmutableList<ObjectId> parentCommits,
      MergeStrategy mergeStrategy) {
    if (parentCommits.isEmpty()) {
      return TreeCreator.basedOnEmptyTree();
    }
    ObjectId baseTreeId = merge(objectInserter, parentCommits, mergeStrategy);
    return TreeCreator.basedOnTree(baseTreeId, parentCommits);
  }

  private static ObjectId merge(
      ObjectInserter objectInserter,
      ImmutableList<ObjectId> parentCommits,
      MergeStrategy mergeStrategy) {
    try {
      Merger merger = mergeStrategy.newMerger(objectInserter, new Config());
      boolean mergeSuccessful = merger.merge(parentCommits.toArray(new AnyObjectId[0]));
      if (!mergeSuccessful) {
        throw new IllegalStateException(
            "Conflicts encountered while merging the specified parents. Use"
                + " mergeOfButBaseOnFirst() instead to avoid these conflicts and define any"
                + " other desired file contents with file().content().");
      }
      return merger.getResultTreeId();
    } catch (IOException e) {
      throw new IllegalStateException(
          "Creating the merge commits of the specified parents failed for an unknown reason.", e);
    }
  }

  private static ObjectId createNewTree(
      Repository repository,
      TreeCreator treeCreator,
      ImmutableList<TreeModification> treeModifications)
      throws IOException {
    treeCreator.addTreeModifications(treeModifications);
    return treeCreator.createNewTreeAndGetId(repository);
  }

  private String correctCommitMessage(String desiredCommitMessage) throws BadRequestException {
    String commitMessage = CommitMessageUtil.checkAndSanitizeCommitMessage(desiredCommitMessage);

    if (ChangeIdUtil.indexOfChangeId(commitMessage, "\n") == -1) {
      ObjectId id = CommitMessageUtil.generateChangeId();
      commitMessage = ChangeIdUtil.insertId(commitMessage, id);
    }

    return commitMessage;
  }

  private ObjectId createCommit(
      ObjectInserter objectInserter,
      ObjectId tree,
      ImmutableList<ObjectId> parentCommitIds,
      PersonIdent author,
      PersonIdent committer,
      String commitMessage)
      throws IOException {
    CommitBuilder builder = new CommitBuilder();
    builder.setTreeId(tree);
    builder.setParentIds(parentCommitIds);
    builder.setAuthor(author);
    builder.setCommitter(committer);
    builder.setMessage(commitMessage);
    ObjectId newCommitId = objectInserter.insert(builder);
    objectInserter.flush();
    return newCommitId;
  }

  private ChangeInserter getChangeInserter(Change.Id changeId, String refName, ObjectId commitId) {
    ChangeInserter inserter = changeInserterFactory.create(changeId, commitId, refName);
    inserter.setMessage(String.format("Uploaded patchset %d.", inserter.getPatchSetId().get()));
    return inserter;
  }

  private class PerChangeOperationsImpl implements PerChangeOperations {

    private final Change.Id changeId;

    public PerChangeOperationsImpl(Change.Id changeId) {
      this.changeId = changeId;
    }

    @Override
    public boolean exists() {
      return changeFinder.findOne(changeId).isPresent();
    }

    @Override
    public TestChange get() {
      return toTestChange(getChangeNotes().getChange());
    }

    private ChangeNotes getChangeNotes() {
      Optional<ChangeNotes> changeNotes = changeFinder.findOne(changeId);
      checkState(changeNotes.isPresent(), "Tried to get non-existing test change.");
      return changeNotes.get();
    }

    private TestChange toTestChange(Change change) {
      return TestChange.builder()
          .numericChangeId(change.getId())
          .changeId(change.getKey().get())
          .build();
    }

    @Override
    public TestPatchsetCreation.Builder newPatchset() {
      return TestPatchsetCreation.builder(this::createPatchset);
    }

    private PatchSet.Id createPatchset(TestPatchsetCreation patchsetCreation)
        throws IOException, RestApiException, UpdateException {
      ChangeNotes changeNotes = getChangeNotes();
      Project.NameKey project = changeNotes.getProjectName();
      try (Repository repository = repositoryManager.openRepository(project);
          ObjectInserter objectInserter = repository.newObjectInserter();
          RevWalk revWalk = new RevWalk(objectInserter.newReader())) {
        Instant now = TimeUtil.now();
        ObjectId newPatchsetCommit =
            createPatchsetCommit(
                repository, revWalk, objectInserter, changeNotes, patchsetCreation, now);

        PatchSet.Id patchsetId =
            ChangeUtil.nextPatchSetId(repository, changeNotes.getCurrentPatchSet().id());
        PatchSetInserter patchSetInserter =
            getPatchSetInserter(changeNotes, newPatchsetCommit, patchsetId);

        IdentifiedUser changeOwner = userFactory.create(changeNotes.getChange().getOwner());
        try (BatchUpdate batchUpdate = batchUpdateFactory.create(project, changeOwner, now)) {
          batchUpdate.setRepository(repository, revWalk, objectInserter);
          batchUpdate.addOp(changeId, patchSetInserter);
          batchUpdate.execute();
        }
        return patchsetId;
      }
    }

    private ObjectId createPatchsetCommit(
        Repository repository,
        RevWalk revWalk,
        ObjectInserter objectInserter,
        ChangeNotes changeNotes,
        TestPatchsetCreation patchsetCreation,
        Instant now)
        throws IOException, BadRequestException {
      ObjectId oldPatchsetCommitId = changeNotes.getCurrentPatchSet().commitId();
      RevCommit oldPatchsetCommit = repository.parseCommit(oldPatchsetCommitId);

      ImmutableList<ObjectId> parentCommitIds =
          getParents(repository, revWalk, patchsetCreation, oldPatchsetCommit);
      TreeCreator treeCreator = getTreeCreator(revWalk, oldPatchsetCommit, parentCommitIds);
      ObjectId tree = createNewTree(repository, treeCreator, patchsetCreation.treeModifications());

      String commitMessage =
          correctCommitMessage(
              changeNotes.getChange().getKey().get(),
              patchsetCreation.commitMessage().orElseGet(oldPatchsetCommit::getFullMessage));

      PersonIdent author = getAuthor(oldPatchsetCommit);
      PersonIdent committer = getCommitter(oldPatchsetCommit, now);
      return createCommit(objectInserter, tree, parentCommitIds, author, committer, commitMessage);
    }

    private String correctCommitMessage(String oldChangeId, String desiredCommitMessage)
        throws BadRequestException {
      String commitMessage = CommitMessageUtil.checkAndSanitizeCommitMessage(desiredCommitMessage);

      // Remove initial 'I' and treat the rest as ObjectId. This is not the cleanest approach but
      // unfortunately, we don't seem to have other utility code which takes the string-based
      // change-id and ensures that it is part of the commit message.
      ObjectId id = ObjectId.fromString(oldChangeId.substring(1));
      commitMessage = ChangeIdUtil.insertId(commitMessage, id, false);

      return commitMessage;
    }

    private PersonIdent getAuthor(RevCommit oldPatchsetCommit) {
      return Optional.ofNullable(oldPatchsetCommit.getAuthorIdent()).orElse(serverIdent);
    }

    private PersonIdent getCommitter(RevCommit oldPatchsetCommit, Instant now) {
      PersonIdent oldPatchsetCommitter =
          Optional.ofNullable(oldPatchsetCommit.getCommitterIdent()).orElse(serverIdent);
      if (asSeconds(now) == asSeconds(oldPatchsetCommitter.getWhenAsInstant())) {
        /* We need to ensure that the resulting commit SHA-1 is different from the old patchset.
         * In real situations, this automatically happens as two patchsets won't have exactly the
         * same commit timestamp even when the tree and commit message are the same. In tests,
         * we can easily end up with the same timestamp as Git uses second precision for timestamps.
         * We could of course require that tests must use TestTimeUtil#setClockStep but
         * that would be an unnecessary nuisance for test writers. Hence, go with a simple solution
         * here and simply add a second. */
        now = now.plusSeconds(1);
      }
      return new PersonIdent(oldPatchsetCommitter, now);
    }

    private long asSeconds(Instant date) {
      return date.getEpochSecond();
    }

    private ImmutableList<ObjectId> getParents(
        Repository repository,
        RevWalk revWalk,
        TestPatchsetCreation patchsetCreation,
        RevCommit oldPatchsetCommit) {
      return patchsetCreation
          .parents()
          .map(parents -> resolveParents(repository, revWalk, parents))
          .orElseGet(
              () -> Arrays.stream(oldPatchsetCommit.getParents()).collect(toImmutableList()));
    }

    private PatchSetInserter getPatchSetInserter(
        ChangeNotes changeNotes, ObjectId newPatchsetCommit, PatchSet.Id patchsetId) {
      PatchSetInserter patchSetInserter =
          patchsetInserterFactory.create(changeNotes, patchsetId, newPatchsetCommit);
      patchSetInserter.setCheckAddPatchSetPermission(false);
      patchSetInserter.setMessage(String.format("Uploaded patchset %d.", patchsetId.get()));
      return patchSetInserter;
    }

    @Override
    public PerPatchsetOperations patchset(PatchSet.Id patchsetId) {
      return perPatchsetOperationsFactory.create(getChangeNotes(), patchsetId);
    }

    @Override
    public PerPatchsetOperations currentPatchset() {
      ChangeNotes changeNotes = getChangeNotes();
      return perPatchsetOperationsFactory.create(
          changeNotes, changeNotes.getChange().currentPatchSetId());
    }

    @Override
    public PerCommentOperations comment(String commentUuid) {
      ChangeNotes changeNotes = getChangeNotes();
      return perCommentOperationsFactory.create(changeNotes, commentUuid);
    }

    @Override
    public PerDraftCommentOperations draftComment(String commentUuid) {
      ChangeNotes changeNotes = getChangeNotes();
      return perDraftCommentOperationsFactory.create(changeNotes, commentUuid);
    }

    @Override
    public PerRobotCommentOperations robotComment(String commentUuid) {
      ChangeNotes changeNotes = getChangeNotes();
      return perRobotCommentOperationsFactory.create(changeNotes, commentUuid);
    }
  }
}
