// 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.patch;

import static com.google.common.collect.Comparators.emptiesFirst;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.groupingBy;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Transformer of {@link Position}s in one Git tree to {@link Position}s in another Git tree given
 * the {@link Mapping}s between the trees.
 *
 * <p>The base idea is that a {@link Position} in the source tree can be translated/mapped to a
 * corresponding {@link Position} in the target tree when we know how the target tree changed
 * compared to the source tree. As long as {@link Position}s are only defined via file path and line
 * range, we only need to know which file path in the source tree corresponds to which file path in
 * the target tree and how the lines within that file changed from the source to the target tree.
 *
 * <p>The algorithm is roughly:
 *
 * <ol>
 *   <li>Go over all positions and replace the file path for each of them with the corresponding one
 *       in the target tree. If a file path maps to two file paths in the target tree (copied file),
 *       duplicate the position entry and use each of the new file paths with it. If a file path
 *       maps to no file in the target tree (deleted file), apply the specified conflict strategy
 *       (e.g. drop position completely or map to next best guess).
 *   <li>Per file path, go through the file from top to bottom and keep track of how the range
 *       mappings for that file shift the lines. Derive the shifted amount by comparing the number
 *       of lines between source and target in the range mapping. While going through the file,
 *       shift each encountered position by the currently tracked amount. If a position overlaps
 *       with the lines of a range mapping, apply the specified conflict strategy (e.g. drop
 *       position completely or map to next best guess).
 * </ol>
 */
public class GitPositionTransformer {
  private final PositionConflictStrategy positionConflictStrategy;

  /**
   * Creates a new {@code GitPositionTransformer} which uses the specified strategy for conflicts.
   */
  public GitPositionTransformer(PositionConflictStrategy positionConflictStrategy) {
    this.positionConflictStrategy = positionConflictStrategy;
  }

  /**
   * Transforms the {@link Position}s of the specified entities as indicated via the {@link
   * Mapping}s.
   *
   * <p>This is typically used to transform the {@link Position}s in one Git tree (source) to the
   * corresponding {@link Position}s in another Git tree (target). The {@link Mapping}s need to
   * indicate all relevant changes between the source and target tree. {@link Mapping}s for files
   * not referenced by the given {@link Position}s need not be specified. They can be included,
   * though, as they aren't harmful.
   *
   * @param entities the entities whose {@link Position} should be mapped to the target tree
   * @param mappings the mappings describing all relevant changes between the source and the target
   *     tree
   * @param <T> an entity which has a {@link Position}
   * @return a list of entities with transformed positions. There are no guarantees about the order
   *     of the returned elements.
   */
  public <T> ImmutableList<PositionedEntity<T>> transform(
      Collection<PositionedEntity<T>> entities, Set<Mapping> mappings) {
    // Update the file paths first as copied files might exist. For copied files, this operation
    // will duplicate the PositionedEntity instances of the original file.
    List<PositionedEntity<T>> filePathUpdatedEntities = updateFilePaths(entities, mappings);

    return shiftRanges(filePathUpdatedEntities, mappings);
  }

  private <T> ImmutableList<PositionedEntity<T>> updateFilePaths(
      Collection<PositionedEntity<T>> entities, Set<Mapping> mappings) {
    Map<String, ImmutableSet<String>> newFilesPerOldFile = groupNewFilesByOldFiles(mappings);
    return entities.stream()
        .flatMap(entity -> mapToNewFileIfChanged(newFilesPerOldFile, entity))
        .collect(toImmutableList());
  }

  private static Map<String, ImmutableSet<String>> groupNewFilesByOldFiles(Set<Mapping> mappings) {
    return mappings.stream()
        .map(Mapping::file)
        // Ignore file additions (irrelevant for mappings).
        .filter(mapping -> mapping.oldPath().isPresent())
        .collect(
            groupingBy(
                mapping -> mapping.oldPath().orElse(""),
                collectingAndThen(
                    Collectors.mapping(FileMapping::newPath, toImmutableSet()),
                    // File deletion (empty Optional) -> empty set.
                    GitPositionTransformer::unwrapOptionals)));
  }

  private static ImmutableSet<String> unwrapOptionals(ImmutableSet<Optional<String>> optionals) {
    return optionals.stream().flatMap(Streams::stream).collect(toImmutableSet());
  }

  private <T> Stream<PositionedEntity<T>> mapToNewFileIfChanged(
      Map<String, ? extends Set<String>> newFilesPerOldFile, PositionedEntity<T> entity) {
    if (!entity.position().filePath().isPresent()) {
      // No mapping of file paths necessary if no file path is set. -> Keep existing entry.
      return Stream.of(entity);
    }
    String oldFilePath = entity.position().filePath().get();
    if (!newFilesPerOldFile.containsKey(oldFilePath)) {
      // Unchanged files don't have a mapping. -> Keep existing entries.
      return Stream.of(entity);
    }
    Set<String> newFiles = newFilesPerOldFile.get(oldFilePath);
    if (newFiles.isEmpty()) {
      // File was deleted.
      return Streams.stream(
          positionConflictStrategy.getOnFileConflict(entity.position()).map(entity::withPosition));
    }
    return newFiles.stream().map(entity::withFilePath);
  }

  private <T> ImmutableList<PositionedEntity<T>> shiftRanges(
      List<PositionedEntity<T>> filePathUpdatedEntities, Set<Mapping> mappings) {
    Map<String, ImmutableSet<RangeMapping>> mappingsPerNewFilePath =
        groupRangeMappingsByNewFilePath(mappings);
    return Stream.concat(
            // Keep positions without a file.
            filePathUpdatedEntities.stream()
                .filter(entity -> !entity.position().filePath().isPresent()),
            // Shift ranges per file.
            groupByFilePath(filePathUpdatedEntities).entrySet().stream()
                .flatMap(
                    newFilePathAndEntities ->
                        shiftRangesInOneFileIfChanged(
                            mappingsPerNewFilePath,
                            newFilePathAndEntities.getKey(),
                            newFilePathAndEntities.getValue())
                            .stream()))
        .collect(toImmutableList());
  }

  private static Map<String, ImmutableSet<RangeMapping>> groupRangeMappingsByNewFilePath(
      Set<Mapping> mappings) {
    return mappings.stream()
        // Ignore range mappings of deleted files.
        .filter(mapping -> mapping.file().newPath().isPresent())
        .collect(
            groupingBy(
                mapping -> mapping.file().newPath().orElse(""),
                collectingAndThen(
                    Collectors.<Mapping, Set<RangeMapping>>reducing(
                        new HashSet<>(), Mapping::ranges, Sets::union),
                    ImmutableSet::copyOf)));
  }

  private static <T> Map<String, ImmutableList<PositionedEntity<T>>> groupByFilePath(
      List<PositionedEntity<T>> fileUpdatedEntities) {
    return fileUpdatedEntities.stream()
        .filter(entity -> entity.position().filePath().isPresent())
        .collect(groupingBy(entity -> entity.position().filePath().orElse(""), toImmutableList()));
  }

  private <T> ImmutableList<PositionedEntity<T>> shiftRangesInOneFileIfChanged(
      Map<String, ImmutableSet<RangeMapping>> mappingsPerNewFilePath,
      String newFilePath,
      ImmutableList<PositionedEntity<T>> sameFileEntities) {
    ImmutableSet<RangeMapping> sameFileRangeMappings =
        mappingsPerNewFilePath.getOrDefault(newFilePath, ImmutableSet.of());
    if (sameFileRangeMappings.isEmpty()) {
      // Unchanged files and pure renames/copies don't have range mappings. -> Keep existing
      // entries.
      return sameFileEntities;
    }
    return shiftRangesInOneFile(sameFileEntities, sameFileRangeMappings);
  }

  private <T> ImmutableList<PositionedEntity<T>> shiftRangesInOneFile(
      List<PositionedEntity<T>> sameFileEntities, Set<RangeMapping> sameFileRangeMappings) {
    ImmutableList<PositionedEntity<T>> sortedEntities = sortByStartEnd(sameFileEntities);
    ImmutableList<RangeMapping> sortedMappings = sortByOldStartEnd(sameFileRangeMappings);

    int shiftedAmount = 0;
    int mappingIndex = 0;
    int entityIndex = 0;
    ImmutableList.Builder<PositionedEntity<T>> resultingEntities =
        ImmutableList.builderWithExpectedSize(sortedEntities.size());
    while (entityIndex < sortedEntities.size() && mappingIndex < sortedMappings.size()) {
      PositionedEntity<T> entity = sortedEntities.get(entityIndex);
      if (entity.position().lineRange().isPresent()) {
        Range range = entity.position().lineRange().get();
        RangeMapping mapping = sortedMappings.get(mappingIndex);
        if (mapping.oldLineRange().end() <= range.start()) {
          shiftedAmount = mapping.newLineRange().end() - mapping.oldLineRange().end();
          mappingIndex++;
        } else if (range.end() <= mapping.oldLineRange().start()) {
          resultingEntities.add(entity.shiftPositionBy(shiftedAmount));
          entityIndex++;
        } else {
          positionConflictStrategy
              .getOnRangeConflict(entity.position())
              .map(entity::withPosition)
              .ifPresent(resultingEntities::add);
          entityIndex++;
        }
      } else {
        // No range -> no need to shift.
        resultingEntities.add(entity);
        entityIndex++;
      }
    }
    for (int i = entityIndex; i < sortedEntities.size(); i++) {
      resultingEntities.add(sortedEntities.get(i).shiftPositionBy(shiftedAmount));
    }
    return resultingEntities.build();
  }

  private static <T> ImmutableList<PositionedEntity<T>> sortByStartEnd(
      List<PositionedEntity<T>> entities) {
    return entities.stream()
        .sorted(
            comparing(
                entity -> entity.position().lineRange(),
                emptiesFirst(comparing(Range::start).thenComparing(Range::end))))
        .collect(toImmutableList());
  }

  private static ImmutableList<RangeMapping> sortByOldStartEnd(Set<RangeMapping> mappings) {
    return mappings.stream()
        .sorted(
            comparing(
                RangeMapping::oldLineRange, comparing(Range::start).thenComparing(Range::end)))
        .collect(toImmutableList());
  }

  /**
   * A mapping from a {@link Position} in one Git commit/tree (source) to a {@link Position} in
   * another Git commit/tree (target).
   */
  @AutoValue
  public abstract static class Mapping {

    /** A mapping describing how the attributes of one file are mapped from source to target. */
    public abstract FileMapping file();

    /**
     * Mappings describing how line ranges within the file indicated by {@link #file()} are mapped
     * from source to target.
     */
    public abstract ImmutableSet<RangeMapping> ranges();

    public static Mapping create(FileMapping fileMapping, Iterable<RangeMapping> rangeMappings) {
      return new AutoValue_GitPositionTransformer_Mapping(
          fileMapping, ImmutableSet.copyOf(rangeMappings));
    }
  }

  /**
   * A mapping of attributes from a file in one Git tree (source) to a file in another Git tree
   * (target).
   *
   * <p>At the moment, only the file path is considered. Other attributes like file mode would be
   * imaginable too but are currently not supported.
   */
  @AutoValue
  public abstract static class FileMapping {

    /** File path in the source tree. For file additions, this is an empty {@link Optional}. */
    public abstract Optional<String> oldPath();

    /**
     * File path in the target tree. Can be the same as {@link #oldPath()} if unchanged. For file
     * deletions, this is an empty {@link Optional}.
     */
    public abstract Optional<String> newPath();

    /**
     * Creates a {@link FileMapping} for a file addition.
     *
     * <p>In the context of {@link GitPositionTransformer}, file additions are irrelevant as no
     * given position in the source tree can refer to such a new file in the target tree. We still
     * provide this factory method so that code outside of {@link GitPositionTransformer} doesn't
     * have to care about such details and can simply create {@link FileMapping}s for any
     * modifications between the trees.
     */
    public static FileMapping forAddedFile(String filePath) {
      return new AutoValue_GitPositionTransformer_FileMapping(
          Optional.empty(), Optional.of(filePath));
    }

    /** Creates a {@link FileMapping} for a file deletion. */
    public static FileMapping forDeletedFile(String filePath) {
      return new AutoValue_GitPositionTransformer_FileMapping(
          Optional.of(filePath), Optional.empty());
    }

    /** Creates a {@link FileMapping} for a file modification. */
    public static FileMapping forModifiedFile(String filePath) {
      return new AutoValue_GitPositionTransformer_FileMapping(
          Optional.of(filePath), Optional.of(filePath));
    }

    /** Creates a {@link FileMapping} for a file renaming. */
    public static FileMapping forRenamedFile(String oldPath, String newPath) {
      return new AutoValue_GitPositionTransformer_FileMapping(
          Optional.of(oldPath), Optional.of(newPath));
    }

    /** Creates a {@link FileMapping} using the old and new paths. */
    public static FileMapping forFile(Optional<String> oldPath, Optional<String> newPath) {
      return new AutoValue_GitPositionTransformer_FileMapping(oldPath, newPath);
    }
  }

  /**
   * A mapping of a line range in one Git tree (source) to the corresponding line range in another
   * Git tree (target).
   */
  @AutoValue
  public abstract static class RangeMapping {

    /** Range in the source tree. */
    public abstract Range oldLineRange();

    /** Range in the target tree. */
    public abstract Range newLineRange();

    /**
     * Creates a new {@code RangeMapping}.
     *
     * @param oldRange see {@link #oldLineRange()}
     * @param newRange see {@link #newLineRange()}
     */
    public static RangeMapping create(Range oldRange, Range newRange) {
      return new AutoValue_GitPositionTransformer_RangeMapping(oldRange, newRange);
    }
  }

  /**
   * A position within the tree of a Git commit.
   *
   * <p>The term 'position' is our own invention. The underlying idea is that a Gerrit comment is at
   * a specific position within the commit of a patchset. That position is defined by the attributes
   * defined in this class.
   *
   * <p>The same thinking can be applied to diff hunks (= JGit edits). Each diff hunk maps a
   * position in one commit (e.g. in the parent of the patchset) to a position in another commit
   * (e.g. in the commit of the patchset).
   *
   * <p>We only refer to lines and not character offsets within the lines here as Git only works
   * with line precision. In theory, we could do better in Gerrit as we also have intraline diffs.
   * Incorporating those requires careful considerations, though.
   */
  @AutoValue
  public abstract static class Position {

    /** Absolute file path. */
    public abstract Optional<String> filePath();

    /**
     * Affected lines. An empty {@link Optional} indicates that this position does not refer to any
     * specific lines (e.g. used for a file comment).
     */
    public abstract Optional<Range> lineRange();

    /**
     * Creates a copy of this {@code Position} whose range is shifted by the indicated amount.
     *
     * <p><strong>Note:</strong> There's no guarantee that this method returns a new instance.
     *
     * @param amount number of lines to shift. Negative values mean moving the range up, positive
     *     values mean moving the range down.
     * @return a {@code Position} instance with the updated range
     */
    public Position shiftBy(int amount) {
      return lineRange()
          .map(range -> toBuilder().lineRange(range.shiftBy(amount)).build())
          .orElse(this);
    }

    /**
     * Creates a copy of this {@code Position} which doesn't refer to any specific lines.
     *
     * <p><strong>Note:</strong> There's no guarantee that this method returns a new instance.
     *
     * @return a {@code Position} instance without a line range
     */
    public Position withoutLineRange() {
      return toBuilder().lineRange(Optional.empty()).build();
    }

    /**
     * Creates a copy of this {@code Position} whose file path is adjusted to the indicated value.
     *
     * <p><strong>Note:</strong> There's no guarantee that this method returns a new instance.
     *
     * @param filePath the new file path to use
     * @return a {@code Position} instance with the indicated file path
     */
    public Position withFilePath(String filePath) {
      return toBuilder().filePath(filePath).build();
    }

    abstract Builder toBuilder();

    public static Builder builder() {
      return new AutoValue_GitPositionTransformer_Position.Builder();
    }

    /** Builder of a {@link Position}. */
    @AutoValue.Builder
    public abstract static class Builder {

      /** See {@link #filePath()}. */
      public abstract Builder filePath(String filePath);

      /** See {@link #lineRange()}. */
      public abstract Builder lineRange(Range lineRange);

      /** See {@link #lineRange()}. */
      public abstract Builder lineRange(Optional<Range> lineRange);

      public abstract Position build();
    }
  }

  /** A range. In the context of {@link GitPositionTransformer}, this is a line range. */
  @AutoValue
  public abstract static class Range {

    /** Start of the range. (inclusive) */
    public abstract int start();

    /** End of the range. (exclusive) */
    public abstract int end();

    /**
     * Creates a copy of this {@code Range} which is shifted by the indicated amount. A shift
     * equally applies to both {@link #start()} end {@link #end()}.
     *
     * <p><strong>Note:</strong> There's no guarantee that this method returns a new instance.
     *
     * @param amount amount to shift. Negative values mean moving the range up, positive values mean
     *     moving the range down.
     * @return a {@code Range} instance with updated start/end
     */
    public Range shiftBy(int amount) {
      return create(start() + amount, end() + amount);
    }

    public static Range create(int start, int end) {
      return new AutoValue_GitPositionTransformer_Range(start, end);
    }
  }

  /**
   * Wrapper around an instance of {@code T} which annotates it with a {@link Position}. Methods
   * such as {@link #shiftPositionBy(int)} and {@link #withFilePath(String)} allow to update the
   * associated {@link Position}. Afterwards, use {@link #getEntityAtUpdatedPosition()} to get an
   * updated version of the {@code T} instance.
   *
   * @param <T> an object/entity type which has a {@link Position}
   */
  public static class PositionedEntity<T> {

    private final T entity;
    private final Position position;
    private final BiFunction<T, Position, T> updatedEntityCreator;

    /**
     * Creates a new {@code PositionedEntity}.
     *
     * @param entity an instance which should be annotated with a {@link Position}
     * @param positionExtractor a function describing how a {@link Position} can be derived from the
     *     given entity
     * @param updatedEntityCreator a function to create a new entity of type {@code T} from an
     *     existing entity and a given {@link Position}. This must return a new instance of type
     *     {@code T}! The existing instance must not be modified!
     * @param <T> an object/entity type which has a {@link Position}
     */
    public static <T> PositionedEntity<T> create(
        T entity,
        Function<T, Position> positionExtractor,
        BiFunction<T, Position, T> updatedEntityCreator) {
      Position position = positionExtractor.apply(entity);
      return new PositionedEntity<>(entity, position, updatedEntityCreator);
    }

    private PositionedEntity(
        T entity, Position position, BiFunction<T, Position, T> updatedEntityCreator) {
      this.entity = entity;
      this.position = position;
      this.updatedEntityCreator = updatedEntityCreator;
    }

    /**
     * Returns the original underlying entity.
     *
     * @return the original instance of {@code T}
     */
    public T getEntity() {
      return entity;
    }

    /**
     * Returns an updated version of the entity to which the internally stored {@link Position} was
     * written back to.
     *
     * @return an updated instance of {@code T}
     */
    public T getEntityAtUpdatedPosition() {
      return updatedEntityCreator.apply(entity, position);
    }

    Position position() {
      return position;
    }

    /**
     * Shifts the tracked {@link Position} by the specified amount.
     *
     * @param amount number of lines to shift. Negative values mean moving the range up, positive
     *     values mean moving the range down.
     * @return a {@code PositionedEntity} with updated {@link Position}
     */
    public PositionedEntity<T> shiftPositionBy(int amount) {
      return new PositionedEntity<>(entity, position.shiftBy(amount), updatedEntityCreator);
    }

    /**
     * Updates the file path of the tracked {@link Position}.
     *
     * @param filePath the new file path to use
     * @return a {@code PositionedEntity} with updated {@link Position}
     */
    public PositionedEntity<T> withFilePath(String filePath) {
      return new PositionedEntity<>(entity, position.withFilePath(filePath), updatedEntityCreator);
    }

    /**
     * Updates the tracked {@link Position}.
     *
     * @return a {@code PositionedEntity} with updated {@link Position}
     */
    public PositionedEntity<T> withPosition(Position newPosition) {
      return new PositionedEntity<>(entity, newPosition, updatedEntityCreator);
    }
  }

  /**
   * Strategy indicating how to handle {@link Position}s for which mapping conflicts exist. A
   * mapping conflict means that a {@link Position} can't be transformed such that it still refers
   * to exactly the same commit content afterwards.
   *
   * <p>Example: A {@link Position} refers to file foo.txt and lines 5-6 which contain the text
   * "Line 5\nLine 6". One of the {@link Mapping}s given to {@link #transform(Collection, Set)}
   * indicates that line 5 of foo.txt was modified to "Line five\nLine 5.1\n". We could derive a
   * transformed {@link Position} (foo.txt, lines 5-7) but that {@link Position} would then refer to
   * the content "Line five\nLine 5.1\nLine 6". If the modification started already in line 4, we
   * could even only guess what the transformed {@link Position} would be.
   */
  public interface PositionConflictStrategy {
    /**
     * Determines an alternate {@link Position} when the range of the position can't be mapped
     * without a conflict.
     *
     * @param oldPosition position in the source tree
     * @return the new {@link Position} or an empty {@link Optional} if the position should be
     *     dropped
     */
    Optional<Position> getOnRangeConflict(Position oldPosition);

    /**
     * Determines an alternate {@link Position} when there is no file for the position (= file
     * deletion) in the target tree.
     *
     * @param oldPosition position in the source tree
     * @return the new {@link Position} or an empty {@link Optional} if the position should be *
     *     dropped
     */
    Optional<Position> getOnFileConflict(Position oldPosition);
  }

  /**
   * A strategy which drops any {@link Position}s on a conflicting mapping. Such a strategy is
   * useful if it's important that any mapped {@link Position} still refers to exactly the same
   * commit content as before. See more details at {@link PositionConflictStrategy}.
   *
   * <p>We need this strategy for computing edits due to rebase.
   */
  public enum OmitPositionOnConflict implements PositionConflictStrategy {
    INSTANCE;

    @Override
    public Optional<Position> getOnRangeConflict(Position oldPosition) {
      return Optional.empty();
    }

    @Override
    public Optional<Position> getOnFileConflict(Position oldPosition) {
      return Optional.empty();
    }
  }

  /**
   * A strategy which tries to select the next suitable {@link Position} on a conflicting mapping.
   * At the moment, this strategy is very basic and only defers to the next higher level (e.g. range
   * unclear -> drop range but keep file reference). This could be improved in the future.
   *
   * <p>We need this strategy for ported comments.
   *
   * <p><strong>Warning:</strong> With this strategy, mapped {@link Position}s are not guaranteed to
   * refer to exactly the same commit content as before. See more details at {@link
   * PositionConflictStrategy}.
   *
   * <p>Contract: This strategy will never drop any {@link Position}.
   */
  public enum BestPositionOnConflict implements PositionConflictStrategy {
    INSTANCE;

    @Override
    public Optional<Position> getOnRangeConflict(Position oldPosition) {
      return Optional.of(oldPosition.withoutLineRange());
    }

    @Override
    public Optional<Position> getOnFileConflict(Position oldPosition) {
      // If there isn't a target file, we can also drop any ranges.
      return Optional.of(Position.builder().build());
    }
  }
}
