// 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.gerrit.testing.TestActionRefUpdateContext.openTestRefUpdateContext;

import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Comment.Status;
import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.Patch;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RobotComment;
import com.google.gerrit.extensions.client.Comment;
import com.google.gerrit.extensions.client.Comment.Range;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.IdentifiedUser.GenericFactory;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.UpdateException;
import com.google.gerrit.server.update.context.RefUpdateContext;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
import java.time.Instant;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevWalk;

/**
 * The implementation of {@link PerPatchsetOperations}.
 *
 * <p>There is only one implementation of {@link PerPatchsetOperations}. Nevertheless, we keep the
 * separation between interface and implementation to enhance clarity.
 */
public class PerPatchsetOperationsImpl implements PerPatchsetOperations {
  private final GitRepositoryManager repositoryManager;
  private final IdentifiedUser.GenericFactory userFactory;
  private final BatchUpdate.Factory batchUpdateFactory;
  private final CommentsUtil commentsUtil;

  private final ChangeNotes changeNotes;
  private final PatchSet.Id patchsetId;

  public interface Factory {
    PerPatchsetOperationsImpl create(ChangeNotes changeNotes, PatchSet.Id patchsetId);
  }

  @Inject
  private PerPatchsetOperationsImpl(
      GitRepositoryManager repositoryManager,
      GenericFactory userFactory,
      BatchUpdate.Factory batchUpdateFactory,
      CommentsUtil commentsUtil,
      @Assisted ChangeNotes changeNotes,
      @Assisted PatchSet.Id patchsetId) {
    this.repositoryManager = repositoryManager;
    this.userFactory = userFactory;
    this.batchUpdateFactory = batchUpdateFactory;
    this.commentsUtil = commentsUtil;
    this.changeNotes = changeNotes;
    this.patchsetId = patchsetId;
  }

  @Override
  public TestPatchset get() {
    PatchSet patchset = changeNotes.getPatchSets().get(patchsetId);
    return TestPatchset.builder().patchsetId(patchsetId).commitId(patchset.commitId()).build();
  }

  @Override
  public TestCommentCreation.Builder newComment() {
    return TestCommentCreation.builder(this::createComment, Status.PUBLISHED);
  }

  @Override
  public TestCommentCreation.Builder newDraftComment() {
    return TestCommentCreation.builder(this::createComment, Status.DRAFT);
  }

  @Override
  public TestRobotCommentCreation.Builder newRobotComment() {
    return TestRobotCommentCreation.builder(this::createRobotComment);
  }

  private String createComment(TestCommentCreation commentCreation)
      throws IOException, RestApiException, UpdateException {

    Project.NameKey project = changeNotes.getProjectName();
    try (RefUpdateContext ctx = openTestRefUpdateContext()) {
      try (Repository repository = repositoryManager.openRepository(project);
          ObjectInserter objectInserter = repository.newObjectInserter();
          RevWalk revWalk = new RevWalk(objectInserter.newReader())) {
        Instant now = TimeUtil.now();

        IdentifiedUser author = getAuthor(commentCreation);
        CommentAdditionOp commentAdditionOp = new CommentAdditionOp(commentCreation);
        try (BatchUpdate batchUpdate = batchUpdateFactory.create(project, author, now)) {
          batchUpdate.setRepository(repository, revWalk, objectInserter);
          batchUpdate.addOp(changeNotes.getChangeId(), commentAdditionOp);
          batchUpdate.execute();
        }
        return commentAdditionOp.createdCommentUuid;
      }
    }
  }

  private IdentifiedUser getAuthor(TestCommentCreation commentCreation) {
    Account.Id authorId = commentCreation.author().orElse(changeNotes.getChange().getOwner());
    return userFactory.create(authorId);
  }

  private IdentifiedUser getAuthor(TestRobotCommentCreation robotCommentCreation) {
    Account.Id authorId = robotCommentCreation.author().orElse(changeNotes.getChange().getOwner());
    return userFactory.create(authorId);
  }

  private static Comment.Range toCommentRange(TestRange range) {
    Comment.Range commentRange = new Range();
    commentRange.startLine = range.start().line();
    commentRange.startCharacter = range.start().charOffset();
    commentRange.endLine = range.end().line();
    commentRange.endCharacter = range.end().charOffset();
    return commentRange;
  }

  private class CommentAdditionOp implements BatchUpdateOp {
    private String createdCommentUuid;
    private final TestCommentCreation commentCreation;

    public CommentAdditionOp(TestCommentCreation commentCreation) {
      this.commentCreation = commentCreation;
    }

    @Override
    public boolean updateChange(ChangeContext context) {
      HumanComment comment = toNewComment(context, commentCreation);
      ChangeUpdate changeUpdate = context.getUpdate(patchsetId);
      changeUpdate.putComment(commentCreation.status(), comment);
      // For published comments, only the tag set on the ChangeUpdate (and not on the HumanComment)
      // matters.
      commentCreation.tag().ifPresent(changeUpdate::setTag);
      createdCommentUuid = comment.key.uuid;
      return true;
    }

    private HumanComment toNewComment(ChangeContext context, TestCommentCreation commentCreation) {
      String message = commentCreation.message().orElse("The text of a test comment.");

      String filePath = commentCreation.file().orElse(Patch.PATCHSET_LEVEL);
      short side = commentCreation.side().orElse(CommentSide.PATCHSET_COMMIT).getNumericSide();
      Boolean unresolved = commentCreation.unresolved().orElse(null);
      String parentUuid = commentCreation.parentUuid().orElse(null);
      Instant createdOn = commentCreation.createdOn().orElse(context.getWhen());
      HumanComment newComment =
          commentsUtil.newHumanComment(
              context.getNotes(),
              context.getUser(),
              createdOn,
              filePath,
              patchsetId,
              side,
              message,
              unresolved,
              parentUuid);
      // For draft comments, only the tag set on the HumanComment (and not on the ChangeUpdate)
      // matters.
      commentCreation.tag().ifPresent(tag -> newComment.tag = tag);

      commentCreation.line().ifPresent(line -> newComment.setLineNbrAndRange(line, null));
      // Specification of range trumps explicit line specification.
      commentCreation
          .range()
          .map(PerPatchsetOperationsImpl::toCommentRange)
          .ifPresent(range -> newComment.setLineNbrAndRange(null, range));

      commentsUtil.setCommentCommitId(
          newComment, context.getChange(), changeNotes.getPatchSets().get(patchsetId));
      return newComment;
    }
  }

  private String createRobotComment(TestRobotCommentCreation robotCommentCreation)
      throws IOException, RestApiException, UpdateException {
    Project.NameKey project = changeNotes.getProjectName();
    try (RefUpdateContext ctx = openTestRefUpdateContext()) {
      try (Repository repository = repositoryManager.openRepository(project);
          ObjectInserter objectInserter = repository.newObjectInserter();
          RevWalk revWalk = new RevWalk(objectInserter.newReader())) {
        Instant now = TimeUtil.now();

        IdentifiedUser author = getAuthor(robotCommentCreation);
        RobotCommentAdditionOp robotCommentAdditionOp =
            new RobotCommentAdditionOp(robotCommentCreation);
        try (BatchUpdate batchUpdate = batchUpdateFactory.create(project, author, now)) {
          batchUpdate.setRepository(repository, revWalk, objectInserter);
          batchUpdate.addOp(changeNotes.getChangeId(), robotCommentAdditionOp);
          batchUpdate.execute();
        }
        return robotCommentAdditionOp.createdRobotCommentUuid;
      }
    }
  }

  private class RobotCommentAdditionOp implements BatchUpdateOp {
    private String createdRobotCommentUuid;
    private final TestRobotCommentCreation robotCommentCreation;

    public RobotCommentAdditionOp(TestRobotCommentCreation robotCommentCreation) {
      this.robotCommentCreation = robotCommentCreation;
    }

    @Override
    public boolean updateChange(ChangeContext context) {
      RobotComment robotComment = toNewRobotComment(context, robotCommentCreation);
      ChangeUpdate changeUpdate = context.getUpdate(patchsetId);
      changeUpdate.putRobotComment(robotComment);
      // For robot comments, only the tag set on the ChangeUpdate (and not on the RobotComment)
      // matters.
      robotCommentCreation.tag().ifPresent(changeUpdate::setTag);
      createdRobotCommentUuid = robotComment.key.uuid;
      return true;
    }

    private RobotComment toNewRobotComment(
        ChangeContext context, TestRobotCommentCreation robotCommentCreation) {
      String message = robotCommentCreation.message().orElse("The text of a test robot comment.");

      String filePath = robotCommentCreation.file().orElse(Patch.PATCHSET_LEVEL);
      short side = robotCommentCreation.side().orElse(CommentSide.PATCHSET_COMMIT).getNumericSide();
      String robotId = robotCommentCreation.robotId().orElse("robot");
      String robotRunId = robotCommentCreation.robotId().orElse("1");
      RobotComment newRobotComment =
          commentsUtil.newRobotComment(
              context, filePath, patchsetId, side, message, robotId, robotRunId);

      // TODO(paiking): This should not be needed, as the tag only matters in ChangeUpdate.
      robotCommentCreation.tag().ifPresent(tag -> newRobotComment.tag = tag);

      robotCommentCreation.line().ifPresent(line -> newRobotComment.setLineNbrAndRange(line, null));
      // Specification of range trumps explicit line specification.
      robotCommentCreation
          .range()
          .map(PerPatchsetOperationsImpl::toCommentRange)
          .ifPresent(range -> newRobotComment.setLineNbrAndRange(null, range));

      robotCommentCreation
          .parentUuid()
          .ifPresent(parentUuid -> newRobotComment.parentUuid = parentUuid);
      robotCommentCreation.url().ifPresent(url -> newRobotComment.url = url);
      if (!robotCommentCreation.properties().isEmpty()) {
        newRobotComment.properties = robotCommentCreation.properties();
      }

      commentsUtil.setCommentCommitId(
          newRobotComment, context.getChange(), changeNotes.getPatchSets().get(patchsetId));
      return newRobotComment;
    }
  }
}
