// 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.server.restapi.change;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static java.util.stream.Collectors.groupingBy;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Comment.Range;
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.metrics.Counter0;
import com.google.gerrit.metrics.Description;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.logging.Metadata;
import com.google.gerrit.server.logging.TraceContext;
import com.google.gerrit.server.logging.TraceContext.TraceTimer;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.patch.DiffMappings;
import com.google.gerrit.server.patch.DiffNotAvailableException;
import com.google.gerrit.server.patch.DiffOperations;
import com.google.gerrit.server.patch.GitPositionTransformer;
import com.google.gerrit.server.patch.GitPositionTransformer.BestPositionOnConflict;
import com.google.gerrit.server.patch.GitPositionTransformer.FileMapping;
import com.google.gerrit.server.patch.GitPositionTransformer.Mapping;
import com.google.gerrit.server.patch.GitPositionTransformer.Position;
import com.google.gerrit.server.patch.GitPositionTransformer.PositionedEntity;
import com.google.gerrit.server.patch.filediff.FileDiffOutput;
import com.google.gerrit.server.patch.filediff.FileEdits;
import com.google.gerrit.server.patch.filediff.TaggedEdit;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;
import org.eclipse.jgit.lib.ObjectId;

/**
 * Container for all logic necessary to port comments to a target patchset.
 *
 * <p>A ported comment is a comment which was left on an earlier patchset and is shown on a later
 * patchset. If a comment eligible for porting (e.g. before target patchset) can't be matched to its
 * exact position in the target patchset, we'll map it to its next best location. This can also
 * include a transformation of a line comment into a file comment.
 */
@Singleton
public class CommentPorter {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  @VisibleForTesting
  @Singleton
  static class Metrics {
    final Counter0 portedAsPatchsetLevel;
    final Counter0 portedAsFileLevel;
    final Counter0 portedAsRangeComments;

    @Inject
    Metrics(MetricMaker metricMaker) {
      portedAsPatchsetLevel =
          metricMaker.newCounter(
              "ported_comments/as_patchset_level",
              new Description("Total number of comments ported as patchset-level comments.")
                  .setRate()
                  .setUnit("count"));
      portedAsFileLevel =
          metricMaker.newCounter(
              "ported_comments/as_file_level",
              new Description("Total number of comments ported as file-level comments.")
                  .setRate()
                  .setUnit("count"));
      portedAsRangeComments =
          metricMaker.newCounter(
              "ported_comments/as_range_comments",
              new Description(
                      "Total number of comments having line/range values in the ported patchset.")
                  .setRate()
                  .setUnit("count"));
    }
  }

  private final DiffOperations diffOperations;
  private final GitPositionTransformer positionTransformer =
      new GitPositionTransformer(BestPositionOnConflict.INSTANCE);
  private final CommentsUtil commentsUtil;
  private final Metrics metrics;

  @Inject
  public CommentPorter(DiffOperations diffOperations, CommentsUtil commentsUtil, Metrics metrics) {
    this.diffOperations = diffOperations;
    this.commentsUtil = commentsUtil;
    this.metrics = metrics;
  }

  /**
   * Ports the given comments to the target patchset.
   *
   * <p>Not all given comments are ported. Only those fulfilling some criteria (e.g. before target
   * patchset) are considered eligible for porting.
   *
   * <p>The returned comments represent the ported version. They don't bear any indication to which
   * patchset they were ported. This is intentional as the target patchset should be obvious from
   * the API or the used REST resources. The returned comments still have the patchset field filled.
   * It contains the reference to the patchset on which the comment was originally left. That
   * patchset number can vary among the returned comments as all comments before the target patchset
   * are potentially eligible for porting.
   *
   * <p>The number of returned comments can be smaller (-> only eligible ones are ported!) or larger
   * compared to the provided comments. The latter happens when files appear as copied in the target
   * patchset. In such a situation, the same comment UUID will occur more than once in the returned
   * comments.
   *
   * @param changeNotes the {@link ChangeNotes} of the change to which the comments belong
   * @param targetPatchset the patchset to which the comments should be ported
   * @param comments the original comments
   * @param filters additional filters to apply to the comments before porting. Only the remaining
   *     comments will be ported.
   * @return the ported comments, in no particular order
   */
  public ImmutableList<HumanComment> portComments(
      ChangeNotes changeNotes,
      PatchSet targetPatchset,
      List<HumanComment> comments,
      List<HumanCommentFilter> filters) {
    try (TraceTimer ignored =
        TraceContext.newTimer(
            "Porting comments", Metadata.builder().patchSetId(targetPatchset.number()).build())) {
      ImmutableList<HumanCommentFilter> allFilters = addDefaultFilters(filters, targetPatchset);
      ImmutableList<HumanComment> relevantComments = filter(comments, allFilters);
      return port(changeNotes, targetPatchset, relevantComments);
    }
  }

  private ImmutableList<HumanCommentFilter> addDefaultFilters(
      List<HumanCommentFilter> filters, PatchSet targetPatchset) {
    // Apply the EarlierPatchsetCommentFilter first as it reduces the amount of comments before
    // more expensive filters are applied.
    HumanCommentFilter earlierPatchsetFilter =
        new EarlierPatchsetCommentFilter(targetPatchset.id());
    return Stream.concat(Stream.of(earlierPatchsetFilter), filters.stream())
        .collect(toImmutableList());
  }

  private ImmutableList<HumanComment> filter(
      List<HumanComment> allComments, ImmutableList<HumanCommentFilter> filters) {
    ImmutableList<HumanComment> filteredComments = ImmutableList.copyOf(allComments);
    for (HumanCommentFilter filter : filters) {
      filteredComments = filter.filter(filteredComments);
    }
    return filteredComments;
  }

  private ImmutableList<HumanComment> port(
      ChangeNotes notes, PatchSet targetPatchset, List<HumanComment> comments) {
    Map<Integer, ImmutableList<HumanComment>> commentsPerPatchset =
        comments.stream().collect(groupingBy(comment -> comment.key.patchSetId, toImmutableList()));

    ImmutableList.Builder<HumanComment> portedComments =
        ImmutableList.builderWithExpectedSize(comments.size());
    for (Integer originalPatchsetId : commentsPerPatchset.keySet()) {
      ImmutableList<HumanComment> patchsetComments = commentsPerPatchset.get(originalPatchsetId);
      PatchSet originalPatchset =
          notes.getPatchSets().get(PatchSet.id(notes.getChangeId(), originalPatchsetId));
      if (originalPatchset != null) {
        portedComments.addAll(
            portSamePatchset(
                notes.getProjectName(),
                notes.getChange(),
                originalPatchset,
                targetPatchset,
                patchsetComments));
      } else {
        logger.atWarning().log(
            String.format(
                "Some comments which should be ported refer to the non-existent patchset %s of"
                    + " change %d. Omitting %d affected comments.",
                originalPatchsetId, notes.getChangeId().get(), patchsetComments.size()));
      }
    }
    return portedComments.build();
  }

  private ImmutableList<HumanComment> portSamePatchset(
      Project.NameKey project,
      Change change,
      PatchSet originalPatchset,
      PatchSet targetPatchset,
      ImmutableList<HumanComment> comments) {
    try (TraceTimer ignored =
        TraceContext.newTimer(
            "Porting comments same patchset",
            Metadata.builder()
                .projectName(project.get())
                .changeId(change.getChangeId())
                .patchSetId(originalPatchset.number())
                .build())) {
      Map<Short, List<HumanComment>> commentsPerSide =
          comments.stream().collect(groupingBy(comment -> comment.side));
      ImmutableList.Builder<HumanComment> portedComments = ImmutableList.builder();
      for (Entry<Short, List<HumanComment>> sideAndComments : commentsPerSide.entrySet()) {
        portedComments.addAll(
            portSamePatchsetAndSide(
                project,
                change,
                originalPatchset,
                targetPatchset,
                sideAndComments.getValue(),
                sideAndComments.getKey()));
      }
      return portedComments.build();
    }
  }

  private ImmutableList<HumanComment> portSamePatchsetAndSide(
      Project.NameKey project,
      Change change,
      PatchSet originalPatchset,
      PatchSet targetPatchset,
      List<HumanComment> comments,
      short side) {
    try (TraceTimer ignored =
        TraceContext.newTimer(
            "Porting comments same patchset and side",
            Metadata.builder()
                .projectName(project.get())
                .changeId(change.getChangeId())
                .patchSetId(originalPatchset.number())
                .commentSide(side)
                .build())) {
      ImmutableSet<Mapping> mappings;
      try {
        mappings = loadMappings(project, change, originalPatchset, targetPatchset, side);
      } catch (Exception e) {
        logger.atWarning().withCause(e).log(
            "Could not determine some necessary diff mappings for porting comments on change %s from"
                + " patchset %s to patchset %s. Mapping %d affected comments to the fallback"
                + " destination.",
            change.getChangeId(),
            originalPatchset.id().getId(),
            targetPatchset.id().getId(),
            comments.size());
        mappings = getFallbackMappings(comments);
      }

      ImmutableList<PositionedEntity<HumanComment>> positionedComments =
          comments.stream().map(this::toPositionedEntity).collect(toImmutableList());
      ImmutableMap<PositionedEntity<HumanComment>, HumanComment> origToPortedMap =
          positionTransformer.transform(positionedComments, mappings).stream()
              .collect(
                  ImmutableMap.toImmutableMap(
                      Function.identity(), PositionedEntity::getEntityAtUpdatedPosition));
      collectMetrics(origToPortedMap);
      return ImmutableList.copyOf(origToPortedMap.values());
    }
  }

  private ImmutableSet<Mapping> loadMappings(
      Project.NameKey project,
      Change change,
      PatchSet originalPatchset,
      PatchSet targetPatchset,
      short side)
      throws DiffNotAvailableException {
    try (TraceTimer ignored =
        TraceContext.newTimer(
            "Loading commit mappings",
            Metadata.builder()
                .projectName(project.get())
                .changeId(change.getChangeId())
                .patchSetId(originalPatchset.number())
                .build())) {
      ObjectId originalCommit = determineCommitId(change, originalPatchset, side);
      ObjectId targetCommit = determineCommitId(change, targetPatchset, side);
      return loadCommitMappings(project, originalCommit, targetCommit);
    }
  }

  private ObjectId determineCommitId(Change change, PatchSet patchset, short side) {
    return commentsUtil
        .determineCommitId(change, patchset, side)
        .orElseThrow(
            () ->
                new IllegalStateException(
                    String.format(
                        "Commit indicated by change %d, patchset %d, side %d doesn't exist.",
                        change.getId().get(), patchset.id().get(), side)));
  }

  private ImmutableSet<Mapping> loadCommitMappings(
      Project.NameKey project, ObjectId originalCommit, ObjectId targetCommit)
      throws DiffNotAvailableException {
    try (TraceTimer ignored =
        TraceContext.newTimer(
            "Computing diffs", Metadata.builder().commit(originalCommit.name()).build())) {
      Map<String, FileDiffOutput> modifiedFiles =
          diffOperations.listModifiedFiles(project, originalCommit, targetCommit);
      return modifiedFiles.values().stream()
          .map(CommentPorter::getFileEdits)
          .map(DiffMappings::toMapping)
          .collect(toImmutableSet());
    }
  }

  private static FileEdits getFileEdits(FileDiffOutput fileDiffOutput) {
    return FileEdits.create(
        fileDiffOutput.edits().stream().map(TaggedEdit::edit).collect(toImmutableList()),
        fileDiffOutput.oldPath(),
        fileDiffOutput.newPath());
  }

  private ImmutableSet<Mapping> getFallbackMappings(List<HumanComment> comments) {
    // Consider all files as deleted. -> Comments will be ported to the fallback destination, which
    // currently are patchset-level comments.
    return comments.stream()
        .map(comment -> comment.key.filename)
        .distinct()
        .map(FileMapping::forDeletedFile)
        .map(fileMapping -> Mapping.create(fileMapping, ImmutableSet.of()))
        .collect(toImmutableSet());
  }

  private PositionedEntity<HumanComment> toPositionedEntity(HumanComment comment) {
    return PositionedEntity.create(
        comment, CommentPorter::extractPosition, CommentPorter::createCommentAtNewPosition);
  }

  private static Position extractPosition(HumanComment comment) {
    Position.Builder positionBuilder = Position.builder();
    // Patchset-level comments don't have a file path. The transformation logic still works when
    // using the magic file path but it doesn't hurt to use the actual representation for "no file"
    // internally.
    if (!Patch.PATCHSET_LEVEL.equals(comment.key.filename)) {
      positionBuilder.filePath(comment.key.filename);
    }
    return positionBuilder.lineRange(extractLineRange(comment)).build();
  }

  /**
   * Returns {@link Optional#empty()} if the {@code comment} parameter is a file comment, or the
   * comment range {start_line, end_line} otherwise.
   */
  private static Optional<GitPositionTransformer.Range> extractLineRange(HumanComment comment) {
    // Line specifications in comment are 1-based. Line specifications in Position are 0-based.
    if (comment.range != null) {
      // The combination of (line, charOffset) is exclusive and must be mapped to an exclusive line.
      int exclusiveEndLine =
          comment.range.endChar > 0 ? comment.range.endLine : comment.range.endLine - 1;
      return Optional.of(
          GitPositionTransformer.Range.create(comment.range.startLine - 1, exclusiveEndLine));
    }
    if (comment.lineNbr > 0) {
      return Optional.of(GitPositionTransformer.Range.create(comment.lineNbr - 1, comment.lineNbr));
    }
    // File comment -> no range.
    return Optional.empty();
  }

  private static HumanComment createCommentAtNewPosition(
      HumanComment originalComment, Position newPosition) {
    HumanComment portedComment = new HumanComment(originalComment);
    portedComment.key.filename = newPosition.filePath().orElse(Patch.PATCHSET_LEVEL);
    if (portedComment.range != null && newPosition.lineRange().isPresent()) {
      // Comment was a range comment and also stayed one.
      portedComment.range =
          toRange(
              newPosition.lineRange().get(),
              portedComment.range.startChar,
              portedComment.range.endChar);
      portedComment.lineNbr = portedComment.range.endLine;
    } else {
      portedComment.range = null;
      // No line -> use 0 = file comment or any other comment type without an explicit line.
      portedComment.lineNbr = newPosition.lineRange().map(range -> range.start() + 1).orElse(0);
    }
    if (Patch.PATCHSET_LEVEL.equals(portedComment.key.filename)) {
      // Correct the side of the comment to Side.REVISION (= 1) if the comment was changed to
      // patchset level.
      portedComment.side = 1;
    }
    return portedComment;
  }

  private static Range toRange(
      GitPositionTransformer.Range lineRange, int originalStartChar, int originalEndChar) {
    int adjustedEndLine = originalEndChar > 0 ? lineRange.end() : lineRange.end() + 1;
    return new Range(lineRange.start() + 1, originalStartChar, adjustedEndLine, originalEndChar);
  }

  /**
   * Collect metrics from the original and ported comments.
   *
   * @param portMap map of the ported comments. The keys contain a {@link PositionedEntity} of the
   *     original comment, and the values contain the transformed comments.
   */
  private void collectMetrics(ImmutableMap<PositionedEntity<HumanComment>, HumanComment> portMap) {
    for (Map.Entry<PositionedEntity<HumanComment>, HumanComment> entry : portMap.entrySet()) {
      HumanComment original = entry.getKey().getEntity();
      HumanComment transformed = entry.getValue();

      if (!Patch.isMagic(original.key.filename)) {
        if (Patch.PATCHSET_LEVEL.equals(transformed.key.filename)) {
          metrics.portedAsPatchsetLevel.increment();
        } else if (extractLineRange(original).isPresent()) {
          if (extractLineRange(transformed).isPresent()) {
            metrics.portedAsRangeComments.increment();
          } else {
            // line range was present in the original comment, but the ported comment is a file
            // level comment.
            metrics.portedAsFileLevel.increment();
          }
        }
      }
    }
  }

  /** A filter which just keeps those comments which are before the given patchset. */
  private static class EarlierPatchsetCommentFilter implements HumanCommentFilter {

    private final PatchSet.Id patchsetId;

    public EarlierPatchsetCommentFilter(PatchSet.Id patchsetId) {
      this.patchsetId = patchsetId;
    }

    @Override
    public ImmutableList<HumanComment> filter(ImmutableList<HumanComment> comments) {
      return comments.stream()
          .filter(comment -> comment.key.patchSetId < patchsetId.get())
          .collect(toImmutableList());
    }
  }
}
