// 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,
              null);
      // 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;
    }
  }
}
