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

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