// 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 com.google.common.base.Strings;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ListMultimap;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Patch.ChangeType;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.server.patch.diff.ModifiedFilesCache;
import com.google.gerrit.server.patch.gitdiff.GitModifiedFilesCache;
import com.google.gerrit.server.patch.gitdiff.ModifiedFile;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.filter.PathFilter;

/**
 * A utility class used by the diff cache interfaces {@link GitModifiedFilesCache} and {@link
 * ModifiedFilesCache}.
 */
public class DiffUtil {

  /**
   * Return the {@code modifiedFiles} input list while merging rewritten entries.
   *
   * <p>Background: In some cases, JGit returns two diff entries (ADDED/DELETED, RENAMED/DELETED,
   * etc...) for the same file path. This happens e.g. when a file's mode is changed between
   * patchsets, for example converting a symlink file to a regular file. We identify this case and
   * return a single modified file with changeType = {@link ChangeType#REWRITE}.
   */
  public static ImmutableList<ModifiedFile> mergeRewrittenModifiedFiles(
      List<ModifiedFile> modifiedFiles) {
    ImmutableList.Builder<ModifiedFile> result = ImmutableList.builder();
    ListMultimap<String, ModifiedFile> byPath = ArrayListMultimap.create();
    modifiedFiles.stream()
        .forEach(
            f -> {
              if (f.changeType() == ChangeType.DELETED) {
                byPath.get(f.oldPath().get()).add(f);
              } else {
                byPath.get(f.newPath().get()).add(f);
              }
            });
    for (String path : byPath.keySet()) {
      List<ModifiedFile> entries = byPath.get(path);
      if (entries.size() == 1) {
        result.add(entries.get(0));
      } else {
        // More than one. Return a single REWRITE entry.
        // Convert the first entry (prioritized according to change type enum order) to REWRITE
        entries.sort(Comparator.comparingInt(o -> o.changeType().ordinal()));
        result.add(entries.get(0).toBuilder().changeType(ChangeType.REWRITE).build());
      }
    }
    return result.build();
  }

  /**
   * Returns the Git tree object ID pointed to by the commitId parameter.
   *
   * @param rw a {@link RevWalk} of an opened repository that is used to walk the commit graph.
   * @param commitId 20 bytes commitId SHA-1 hash.
   * @return Git tree object ID pointed to by the commitId.
   */
  public static ObjectId getTreeId(RevWalk rw, ObjectId commitId) throws IOException {
    RevCommit current = rw.parseCommit(commitId);
    return current.getTree().getId();
  }

  /**
   * Returns the RevCommit object given the 20 bytes commitId SHA-1 hash.
   *
   * @param rw a {@link RevWalk} of an opened repository that is used to walk the commit graph.
   * @param commitId 20 bytes commitId SHA-1 hash
   * @return The RevCommit representing the commit in Git
   * @throws IOException a pack file or loose object could not be read while parsing the commits.
   */
  public static RevCommit getRevCommit(RevWalk rw, ObjectId commitId) throws IOException {
    return rw.parseCommit(commitId);
  }

  /**
   * Returns true if the commitA and commitB parameters are parent/child, if they have a common
   * parent, or if any of them is a root or merge commit.
   */
  public static boolean areRelated(RevCommit commitA, RevCommit commitB) {
    return commitA == null
        || isRootOrMergeCommit(commitA)
        || isRootOrMergeCommit(commitB)
        || areParentAndChild(commitA, commitB)
        || haveCommonParent(commitA, commitB);
  }

  public static int stringSize(String str) {
    if (str != null) {
      // each character in the string occupies 2 bytes. Ignoring the fixed overhead for the string
      // (length, offset and hash code) since they are negligible and do not affect the comparison
      // of 2 strings.
      return str.length() * 2;
    }
    return 0;
  }

  /**
   * Get formatted diff between the given commits, either for a single path if specified, or for the
   * full trees.
   *
   * @param repo to get the diff from
   * @param baseCommit to compare with
   * @param childCommit to compare
   * @param path to narrow the diff to
   * @param out to append the diff to
   * @throws IOException if the diff couldn't be written
   */
  public static void getFormattedDiff(
      Repository repo,
      RevCommit baseCommit,
      RevCommit childCommit,
      @Nullable String path,
      OutputStream out)
      throws IOException {
    getFormattedDiff(repo, null, baseCommit.getTree(), childCommit.getTree(), path, out);
  }

  public static void getFormattedDiff(
      Repository repo,
      @Nullable ObjectReader reader,
      RevTree baseTree,
      RevTree childTree,
      @Nullable String path,
      OutputStream out)
      throws IOException {
    try (DiffFormatter fmt = new DiffFormatter(out)) {
      fmt.setRepository(repo);
      if (reader != null) {
        fmt.setReader(reader, repo.getConfig());
      }
      if (path != null) {
        fmt.setPathFilter(PathFilter.create(path));
      }
      fmt.format(baseTree, childTree);
      fmt.flush();
    }
  }

  public static String normalizePatchForComparison(final String patch) {
    String res = removePatchHeader(patch);
    return res
        // Remove any lines which are not diff lines or file header lines - such index,
        // hunk-headers, and context lines.
        .replaceAll("(?m)^[^+-].*", "")
        .replaceAll("(?m)^[+]{3} [ab]/", "+++ ")
        .replaceAll("(?m)^-{3} [ab]/", "--- ")
        // Remove empty lines
        .replaceAll("\n+", "\n")
        // Trim
        .trim();
  }

  public static String removePatchHeader(final String patch) {
    String res = patch.trim();
    if (!res.startsWith("diff --") && res.contains("\ndiff --")) {
      return res.substring(res.indexOf("\ndiff --"));
    }
    return res;
  }

  public static Optional<String> getPatchHeader(final String patch) {
    String res = patch.trim();
    if (res.startsWith("diff ")) {
      return Optional.empty();
    }
    return Optional.ofNullable(Strings.emptyToNull(res.substring(0, res.indexOf("\ndiff "))));
  }

  public static String normalizePatchForComparison(BinaryResult bin) throws IOException {
    return normalizePatchForComparison(bin.asString());
  }

  private static boolean isRootOrMergeCommit(RevCommit commit) {
    return commit.getParentCount() != 1;
  }

  private static boolean areParentAndChild(RevCommit commitA, RevCommit commitB) {
    return ObjectId.isEqual(commitA.getParent(0), commitB)
        || ObjectId.isEqual(commitB.getParent(0), commitA);
  }

  private static boolean haveCommonParent(RevCommit commitA, RevCommit commitB) {
    return ObjectId.isEqual(commitA.getParent(0), commitB.getParent(0));
  }
}
