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

import com.google.common.collect.ImmutableMap;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.server.patch.DiffNotAvailableException;
import com.google.gerrit.server.patch.DiffUtil;
import com.google.gerrit.server.patch.gitfilediff.GitFileDiff;
import com.google.gerrit.server.patch.gitfilediff.GitFileDiffCache;
import com.google.gerrit.server.patch.gitfilediff.GitFileDiffCacheKey;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.revwalk.RevWalk;

/**
 * A helper class that computes the four {@link GitFileDiff}s for a list of {@link
 * FileDiffCacheKey}s:
 *
 * <ul>
 *   <li>old commit vs. new commit
 *   <li>old parent vs. old commit
 *   <li>new parent vs. new commit
 *   <li>old parent vs. new parent
 * </ul>
 *
 * The four {@link GitFileDiff} are stored in the entity class {@link AllFileGitDiffs}. We use these
 * diffs to identify the edits due to rebase using the {@link EditTransformer} class.
 */
class AllDiffsEvaluator {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final RevWalk rw;
  private final GitFileDiffCache gitCache;

  interface Factory {
    AllDiffsEvaluator create(RevWalk rw);
  }

  @Inject
  private AllDiffsEvaluator(GitFileDiffCache gitCache, @Assisted RevWalk rw) {
    this.gitCache = gitCache;
    this.rw = rw;
  }

  Map<AugmentedFileDiffCacheKey, AllFileGitDiffs> execute(
      List<AugmentedFileDiffCacheKey> augmentedKeys) throws DiffNotAvailableException {
    ImmutableMap.Builder<AugmentedFileDiffCacheKey, AllFileGitDiffs> keyToAllDiffs =
        ImmutableMap.builderWithExpectedSize(augmentedKeys.size());

    List<AugmentedFileDiffCacheKey> keysWithRebaseEdits =
        augmentedKeys.stream().filter(k -> !k.ignoreRebase()).collect(Collectors.toList());

    // TODO(ghareeb): as an enhancement, you can batch these calls as follows.
    // First batch: "old commit vs. new commit" and "new parent vs. new commit"
    // Second batch: "old parent vs. old commit" and "old parent vs. new parent"

    Map<FileDiffCacheKey, GitDiffEntity> mainDiffs =
        computeGitFileDiffs(
            createGitKeys(
                augmentedKeys,
                k -> k.key().oldCommit(),
                k -> k.key().newCommit(),
                k -> k.key().newFilePath()));

    Map<FileDiffCacheKey, GitDiffEntity> oldVsParentDiffs =
        computeGitFileDiffs(
            createGitKeys(
                keysWithRebaseEdits,
                k -> k.oldParentId().get(), // oldParent is set for keysWithRebaseEdits
                k -> k.key().oldCommit(),
                k -> mainDiffs.get(k.key()).gitDiff().oldPath().orElse(null)));

    Map<FileDiffCacheKey, GitDiffEntity> newVsParentDiffs =
        computeGitFileDiffs(
            createGitKeys(
                keysWithRebaseEdits,
                k -> k.newParentId().get(), // newParent is set for keysWithRebaseEdits
                k -> k.key().newCommit(),
                k -> k.key().newFilePath()));

    Map<FileDiffCacheKey, GitDiffEntity> parentsDiffs =
        computeGitFileDiffs(
            createGitKeys(
                keysWithRebaseEdits,
                k -> k.oldParentId().get(),
                k -> k.newParentId().get(),
                k -> {
                  GitFileDiff newVsParDiff = newVsParentDiffs.get(k.key()).gitDiff();
                  // TODO(ghareeb): Follow up on replacing key.newFilePath as a fallback.
                  // If the file was added between newParent and newCommit, we actually wouldn't
                  // need to have to determine the oldParent vs. newParent diff as nothing in
                  // that file could be an edit due to rebase anymore. Only if the returned diff
                  // is empty, the oldParent vs. newParent diff becomes relevant again (e.g. to
                  // identify a file deletion which was due to rebase. Check if the structure
                  // can be improved to make this clearer. Can we maybe even skip the diff in
                  // the first situation described?
                  return newVsParDiff.oldPath().orElse(k.key().newFilePath());
                }));

    for (AugmentedFileDiffCacheKey augmentedKey : augmentedKeys) {
      FileDiffCacheKey key = augmentedKey.key();
      AllFileGitDiffs.Builder builder =
          AllFileGitDiffs.builder().augmentedKey(augmentedKey).mainDiff(mainDiffs.get(key));

      if (augmentedKey.ignoreRebase()) {
        keyToAllDiffs.put(augmentedKey, builder.build());
        continue;
      }

      if (oldVsParentDiffs.containsKey(key) && !oldVsParentDiffs.get(key).gitDiff().isEmpty()) {
        builder.oldVsParentDiff(Optional.of(oldVsParentDiffs.get(key)));
      }

      if (newVsParentDiffs.containsKey(key) && !newVsParentDiffs.get(key).gitDiff().isEmpty()) {
        builder.newVsParentDiff(Optional.of(newVsParentDiffs.get(key)));
      }

      if (parentsDiffs.containsKey(key) && !parentsDiffs.get(key).gitDiff().isEmpty()) {
        builder.parentVsParentDiff(Optional.of(parentsDiffs.get(key)));
      }

      keyToAllDiffs.put(augmentedKey, builder.build());
    }
    return keyToAllDiffs.build();
  }

  /**
   * Computes the git diff for the git keys of the input map {@code keys} parameter. The computation
   * uses the underlying {@link GitFileDiffCache}.
   */
  private Map<FileDiffCacheKey, GitDiffEntity> computeGitFileDiffs(
      Map<FileDiffCacheKey, GitFileDiffCacheKey> keys) throws DiffNotAvailableException {
    ImmutableMap.Builder<FileDiffCacheKey, GitDiffEntity> result =
        ImmutableMap.builderWithExpectedSize(keys.size());
    ImmutableMap<GitFileDiffCacheKey, GitFileDiff> gitDiffs = gitCache.getAll(keys.values());
    for (FileDiffCacheKey key : keys.keySet()) {
      GitFileDiffCacheKey gitKey = keys.get(key);
      GitFileDiff gitFileDiff = gitDiffs.get(gitKey);
      result.put(key, GitDiffEntity.create(gitKey, gitFileDiff));
    }
    return result.build();
  }

  /**
   * Convert a list of {@link AugmentedFileDiffCacheKey} to their corresponding {@link
   * GitFileDiffCacheKey} which can be used to call the underlying {@link GitFileDiffCache}.
   *
   * @param keys a list of input {@link AugmentedFileDiffCacheKey}s.
   * @param aCommitFn a function to compute the aCommit that will be used in the git diff.
   * @param bCommitFn a function to compute the bCommit that will be used in the git diff.
   * @param newPathFn a function to compute the new path of the git key.
   * @return a map of the input {@link FileDiffCacheKey} to the {@link GitFileDiffCacheKey}.
   */
  private Map<FileDiffCacheKey, GitFileDiffCacheKey> createGitKeys(
      List<AugmentedFileDiffCacheKey> keys,
      Function<AugmentedFileDiffCacheKey, ObjectId> aCommitFn,
      Function<AugmentedFileDiffCacheKey, ObjectId> bCommitFn,
      Function<AugmentedFileDiffCacheKey, String> newPathFn) {
    Map<FileDiffCacheKey, GitFileDiffCacheKey> result = new HashMap<>();
    for (AugmentedFileDiffCacheKey key : keys) {
      try {
        String path = newPathFn.apply(key);
        if (path != null) {
          result.put(
              key.key(),
              createGitKey(key.key(), aCommitFn.apply(key), bCommitFn.apply(key), path, rw));
        }
      } catch (IOException e) {
        // TODO(ghareeb): This implies that the output keys may not have the same size as the input.
        // Check the caller's code path about the correctness of the computation in this case. If
        // errors are rare, it may be better to throw an exception and fail the whole computation.
        logger.atWarning().log("Failed to compute the git key for key %s: %s", key, e.getMessage());
      }
    }
    return result;
  }

  /** Returns the {@link GitFileDiffCacheKey} for the {@code key} input parameter. */
  private GitFileDiffCacheKey createGitKey(
      FileDiffCacheKey key, ObjectId aCommit, ObjectId bCommit, String pathNew, RevWalk rw)
      throws IOException {
    ObjectId oldTreeId =
        aCommit.equals(ObjectId.zeroId()) ? ObjectId.zeroId() : DiffUtil.getTreeId(rw, aCommit);
    ObjectId newTreeId = DiffUtil.getTreeId(rw, bCommit);
    return GitFileDiffCacheKey.builder()
        .project(key.project())
        .oldTree(oldTreeId)
        .newTree(newTreeId)
        .newFilePath(pathNew == null ? key.newFilePath() : pathNew)
        .renameScore(key.renameScore())
        .diffAlgorithm(key.diffAlgorithm())
        .whitespace(key.whitespace())
        .useTimeout(key.useTimeout())
        .build();
  }
}
