// Copyright (C) 2014 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.server;

import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.toCollection;
import static java.util.stream.Collectors.toList;

import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.ChangeMessage;
import com.google.gerrit.entities.Comment;
import com.google.gerrit.entities.FixReplacement;
import com.google.gerrit.entities.FixSuggestion;
import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RobotComment;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.client.Side;
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.common.FixReplacementInfo;
import com.google.gerrit.extensions.common.FixSuggestionInfo;
import com.google.gerrit.server.config.GerritServerId;
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.patch.DiffNotAvailableException;
import com.google.gerrit.server.patch.DiffOperations;
import com.google.gerrit.server.patch.DiffOptions;
import com.google.gerrit.server.patch.filediff.FileDiffOutput;
import com.google.gerrit.server.update.ChangeContext;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;

/** Utility functions to manipulate Comments. */
@Singleton
public class CommentsUtil {
  public static final Ordering<Comment> COMMENT_ORDER =
      new Ordering<>() {
        @Override
        public int compare(Comment c1, Comment c2) {
          return ComparisonChain.start()
              .compare(c1.key.filename, c2.key.filename)
              .compare(c1.key.patchSetId, c2.key.patchSetId)
              .compare(c1.side, c2.side)
              .compare(c1.lineNbr, c2.lineNbr)
              .compare(c1.writtenOn, c2.writtenOn)
              .result();
        }
      };

  public static final Ordering<CommentInfo> COMMENT_INFO_ORDER =
      new Ordering<>() {
        @Override
        public int compare(CommentInfo a, CommentInfo b) {
          return ComparisonChain.start()
              .compare(a.path, b.path, NULLS_FIRST)
              .compare(a.patchSet, b.patchSet, NULLS_FIRST)
              .compare(side(a), side(b))
              .compare(a.line, b.line, NULLS_FIRST)
              .compare(a.inReplyTo, b.inReplyTo, NULLS_FIRST)
              .compare(a.message, b.message)
              .compare(a.id, b.id)
              .result();
        }

        private int side(CommentInfo c) {
          return firstNonNull(c.side, Side.REVISION).ordinal();
        }
      };

  public static PatchSet.Id getCommentPsId(Change.Id changeId, Comment comment) {
    return PatchSet.id(changeId, comment.key.patchSetId);
  }

  @Nullable
  public static String extractMessageId(@Nullable String tag) {
    if (tag == null || !tag.startsWith("mailMessageId=")) {
      return null;
    }
    return tag.substring("mailMessageId=".length());
  }

  private static final Ordering<Comparable<?>> NULLS_FIRST = Ordering.natural().nullsFirst();

  private final DiffOperations diffOperations;
  private final GitRepositoryManager repoManager;
  private final String serverId;

  @Inject
  CommentsUtil(
      DiffOperations diffOperations,
      GitRepositoryManager repoManager,
      @GerritServerId String serverId) {
    this.diffOperations = diffOperations;
    this.repoManager = repoManager;
    this.serverId = serverId;
  }

  public HumanComment newHumanComment(
      ChangeNotes changeNotes,
      CurrentUser currentUser,
      Instant when,
      String path,
      PatchSet.Id psId,
      short side,
      String message,
      @Nullable Boolean unresolved,
      @Nullable String parentUuid,
      @Nullable List<FixSuggestion> fixSuggestions) {
    if (unresolved == null) {
      if (parentUuid == null) {
        // Default to false if comment is not descended from another.
        unresolved = false;
      } else {
        // Inherit unresolved value from inReplyTo comment if not specified.
        Comment.Key key = new Comment.Key(parentUuid, path, psId.get());
        Optional<HumanComment> parent = getPublishedHumanComment(changeNotes, key);

        // If the comment was not found, it is descended from a robot comment, or the UUID is
        // invalid. Either way, we use the default.
        unresolved = parent.map(p -> p.unresolved).orElse(false);
      }
    }
    HumanComment c =
        new HumanComment(
            new Comment.Key(ChangeUtil.messageUuid(), path, psId.get()),
            currentUser.getAccountId(),
            when,
            side,
            message,
            serverId,
            unresolved);
    c.parentUuid = parentUuid;
    c.fixSuggestions = fixSuggestions;
    currentUser.updateRealAccountId(c::setRealAuthor);
    return c;
  }

  public RobotComment newRobotComment(
      ChangeContext ctx,
      String path,
      PatchSet.Id psId,
      short side,
      String message,
      String robotId,
      String robotRunId) {
    RobotComment c =
        new RobotComment(
            new Comment.Key(ChangeUtil.messageUuid(), path, psId.get()),
            ctx.getUser().getAccountId(),
            ctx.getWhen(),
            side,
            message,
            serverId,
            robotId,
            robotRunId);
    ctx.getUser().updateRealAccountId(c::setRealAuthor);
    return c;
  }

  public Optional<HumanComment> getPublishedHumanComment(ChangeNotes notes, Comment.Key key) {
    return publishedHumanCommentsByChange(notes).stream()
        .filter(c -> key.equals(c.key))
        .findFirst();
  }

  public Optional<HumanComment> getPublishedHumanComment(ChangeNotes notes, String uuid) {
    return publishedHumanCommentsByChange(notes).stream()
        .filter(c -> c.key.uuid.equals(uuid))
        .findFirst();
  }

  public List<HumanComment> publishedHumanCommentsByChange(ChangeNotes notes) {
    notes.load();
    return sort(Lists.newArrayList(notes.getHumanComments().values()));
  }

  public List<RobotComment> robotCommentsByChange(ChangeNotes notes) {
    notes.load();
    return sort(Lists.newArrayList(notes.getRobotComments().values()));
  }

  public Optional<RobotComment> getRobotComment(ChangeNotes notes, String uuid) {
    return robotCommentsByChange(notes).stream().filter(c -> c.key.uuid.equals(uuid)).findFirst();
  }

  public List<HumanComment> publishedByPatchSet(ChangeNotes notes, PatchSet.Id psId) {
    return commentsOnPatchSet(notes.load().getHumanComments().values(), psId);
  }

  public List<RobotComment> robotCommentsByPatchSet(ChangeNotes notes, PatchSet.Id psId) {
    return commentsOnPatchSet(notes.load().getRobotComments().values(), psId);
  }

  /**
   * This method populates the "changeMessageId" field of the comments parameter based on timestamp
   * matching. The comments objects will be modified.
   *
   * <p>Each comment will be matched to the nearest next change message in timestamp
   *
   * @param comments the list of comments
   * @param changeMessages list of change messages
   */
  public static void linkCommentsToChangeMessages(
      List<? extends CommentInfo> comments,
      List<ChangeMessage> changeMessages,
      boolean skipAutoGeneratedMessages) {

    // First sort by timestamp, then by authorId so that we could move on to the next change message
    // in case multiple accounts left comments at the same timestamp.
    ArrayList<ChangeMessage> sortedChangeMessages =
        changeMessages.stream()
            .sorted(
                comparing(ChangeMessage::getWrittenOn)
                    .thenComparingInt(c -> c.getAuthor() == null ? 0 : c.getAuthor().get()))
            .collect(toCollection(ArrayList::new));

    ArrayList<CommentInfo> sortedCommentInfos =
        comments.stream()
            .sorted(
                comparing(CommentInfo::getUpdated)
                    .thenComparingInt(c -> c.author == null ? 0 : c.author._accountId))
            .collect(toCollection(ArrayList::new));

    int cmItr = 0;
    int lastMatch = 0;
    for (CommentInfo comment : sortedCommentInfos) {
      // Keep advancing the change message pointer until we associate the comment to the next change
      // message in timestamp
      while (cmItr < sortedChangeMessages.size()) {
        ChangeMessage cm = sortedChangeMessages.get(cmItr);
        if (isAfter(comment, cm)
            || !haveSameAuthor(cm, comment)
            || (skipAutoGeneratedMessages && isAutoGenerated(cm))) {
          cmItr += 1;
        } else {
          lastMatch = cmItr;
          break;
        }
      }
      if (cmItr < changeMessages.size()) {
        comment.changeMessageId = sortedChangeMessages.get(cmItr).getKey().uuid();
      } else {
        // In case of no match "cmItr" will never be less than "changeMessages" size, hence the
        // changeMessageId won't be set for any comment.
        //
        // Reset the search to the last succesful match, since we can't assume there will always be
        // a match between change messages and comments. This could be the case of imported changes.
        //
        // More details here: https://issues.gerritcodereview.com/issues/318079520
        cmItr = lastMatch;
      }
    }
  }

  private static boolean isAutoGenerated(ChangeMessage cm) {
    // Ignore Gerrit auto-generated messages, allowing to link against human change messages that
    // have an auto-generated tag
    return ChangeMessagesUtil.isAutogeneratedByGerrit(cm.getTag());
  }

  private static boolean isAfter(CommentInfo c, ChangeMessage cm) {
    return c.getUpdated().isAfter(cm.getWrittenOn());
  }

  private static boolean haveSameAuthor(ChangeMessage cm, CommentInfo comment) {
    return Objects.equals(
        Optional.ofNullable(cm.getAuthor()).map(a -> a.get()),
        Optional.ofNullable(comment.author).map(a -> a._accountId));
  }

  public void putHumanComments(
      ChangeUpdate update, Comment.Status status, Iterable<HumanComment> comments) {
    for (HumanComment c : comments) {
      update.putComment(status, c);
    }
  }

  public void putRobotComments(ChangeUpdate update, Iterable<RobotComment> comments) {
    for (RobotComment c : comments) {
      update.putRobotComment(c);
    }
  }

  public void deleteHumanComments(ChangeUpdate update, Iterable<HumanComment> comments) {
    for (HumanComment c : comments) {
      update.deleteComment(c);
    }
  }

  public void deleteCommentByRewritingHistory(
      ChangeUpdate update, Comment.Key commentKey, String newMessage) {
    update.deleteCommentByRewritingHistory(commentKey.uuid, newMessage);
  }

  private static <T extends Comment> List<T> commentsOnPatchSet(
      Collection<T> allComments, PatchSet.Id psId) {
    List<T> result = new ArrayList<>(allComments.size());
    for (T c : allComments) {
      if (c.key.patchSetId == psId.get()) {
        result.add(c);
      }
    }
    return sort(result);
  }

  public void setCommentCommitId(Comment c, Change change, PatchSet ps) {
    if (c.getCommitId() == null) {
      checkArgument(
          c.key.patchSetId == ps.id().get(),
          "cannot set commit ID for patch set %s on comment %s",
          ps.id(),
          c);

      // This code is very much down into our stack and shouldn't be used for validation. Hence,
      // don't throw an exception here if we can't find a commit for the indicated side but
      // simply use the all-null ObjectId.
      c.setCommitId(determineCommitId(change, ps, c.side).orElseGet(ObjectId::zeroId));
    }
  }

  /**
   * Determines the SHA-1 of the commit referenced by the (change, patchset, side) triple.
   *
   * @param change the change to which the commit belongs
   * @param patchset the patchset to which the commit belongs
   * @param side the side indicating which commit of the patchset to take. 1 is the patchset commit,
   *     0 the parent commit (or auto-merge for changes representing merge commits); -x the xth
   *     parent commit of a merge commit
   * @return the commit SHA-1 or an empty {@link Optional} if the side isn't available for the given
   *     change/patchset
   * @throws StorageException if the SHA-1 is unavailable for an unknown reason
   */
  public Optional<ObjectId> determineCommitId(Change change, PatchSet patchset, short side) {
    if (Side.fromShort(side) == Side.PARENT) {
      if (side < 0) {
        int parentNumber = Math.abs(side);
        return resolveParentCommit(change.getProject(), patchset, parentNumber);
      }
      return Optional.ofNullable(resolveAutoMergeCommit(change, patchset));
    }
    return Optional.of(patchset.commitId());
  }

  private Optional<ObjectId> resolveParentCommit(
      Project.NameKey project, PatchSet patchset, int parentNumber) {
    try (Repository repository = repoManager.openRepository(project)) {
      RevCommit commit = repository.parseCommit(patchset.commitId());
      if (commit.getParentCount() < parentNumber) {
        return Optional.empty();
      }
      return Optional.of(commit.getParent(parentNumber - 1));
    } catch (IOException e) {
      throw new StorageException(e);
    }
  }

  @Nullable
  private ObjectId resolveAutoMergeCommit(Change change, PatchSet patchset) {
    try {
      // TODO(ghareeb): Adjust after the auto-merge code was moved out of the diff caches. Also
      // unignore the test in PortedCommentsIT.
      Map<String, FileDiffOutput> modifiedFiles =
          diffOperations.listModifiedFilesAgainstParent(
              change.getProject(), patchset.commitId(), /* parentNum= */ 0, DiffOptions.DEFAULTS);
      return modifiedFiles.isEmpty()
          ? null
          : modifiedFiles.values().iterator().next().oldCommitId();
    } catch (DiffNotAvailableException e) {
      throw new StorageException(e);
    }
  }

  public static <T extends Comment> List<T> sort(List<T> comments) {
    comments.sort(COMMENT_ORDER);
    return comments;
  }

  @Nullable
  public static ImmutableList<FixSuggestion> createFixSuggestionsFromInput(
      List<FixSuggestionInfo> fixSuggestionInfos) {
    if (fixSuggestionInfos == null) {
      return null;
    }

    ImmutableList.Builder<FixSuggestion> fixSuggestions =
        ImmutableList.builderWithExpectedSize(fixSuggestionInfos.size());
    for (FixSuggestionInfo fixSuggestionInfo : fixSuggestionInfos) {
      fixSuggestions.add(createFixSuggestionFromInput(fixSuggestionInfo));
    }
    return fixSuggestions.build();
  }

  public static FixSuggestion createFixSuggestionFromInput(FixSuggestionInfo fixSuggestionInfo) {
    List<FixReplacement> fixReplacements = toFixReplacements(fixSuggestionInfo.replacements);
    String fixId = ChangeUtil.messageUuid();
    return new FixSuggestion(fixId, fixSuggestionInfo.description, fixReplacements);
  }

  public static List<FixReplacement> toFixReplacements(
      List<FixReplacementInfo> fixReplacementInfos) {
    return fixReplacementInfos.stream().map(CommentsUtil::toFixReplacement).collect(toList());
  }

  public static FixReplacement toFixReplacement(FixReplacementInfo fixReplacementInfo) {
    Comment.Range range = new Comment.Range(fixReplacementInfo.range);
    return new FixReplacement(fixReplacementInfo.path, range, fixReplacementInfo.replacement);
  }
}
