// Copyright (C) 2021 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.gerrit.server.project.ProjectCache.illegalState;

import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.data.PatchScript;
import com.google.gerrit.entities.LabelId;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.entities.Patch;
import com.google.gerrit.entities.Patch.ChangeType;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.PatchSetApproval;
import com.google.gerrit.entities.Project;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.client.DiffPreferencesInfo;
import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.diff.DiffInfoCreator;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.LargeObjectException;
import com.google.gerrit.server.git.validators.CommentCumulativeSizeValidator;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.patch.filediff.FileDiffOutput;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.util.RawParseUtils;
import org.eclipse.jgit.util.TemporaryBuffer;

/**
 * This class is used on submit to compute the diff between the latest approved patch-set, and the
 * current submitted patch-set.
 *
 * <p>Latest approved patch-set is defined by the latest patch-set which has Code-Review label voted
 * with the maximum possible value.
 *
 * <p>If the latest approved patch-set is the same as the submitted patch-set, the diff will be
 * empty.
 *
 * <p>We exclude the magic files from the returned diff to make it shorter and more concise.
 */
public class SubmitWithStickyApprovalDiff {
  private static final int HEAP_EST_SIZE = 32 * 1024;
  private static final int DEFAULT_POST_SUBMIT_SIZE_LIMIT = 300 * 1024; // 300 KiB

  private final DiffOperations diffOperations;
  private final ProjectCache projectCache;
  private final PatchScriptFactory.Factory patchScriptFactoryFactory;
  private final GitRepositoryManager repositoryManager;
  private final int maxCumulativeSize;

  @Inject
  SubmitWithStickyApprovalDiff(
      DiffOperations diffOperations,
      ProjectCache projectCache,
      PatchScriptFactory.Factory patchScriptFactoryFactory,
      GitRepositoryManager repositoryManager,
      @GerritServerConfig Config serverConfig) {
    this.diffOperations = diffOperations;
    this.projectCache = projectCache;
    this.patchScriptFactoryFactory = patchScriptFactoryFactory;
    this.repositoryManager = repositoryManager;
    // (November 2021) We define the max cumulative comment size to 300 KIB since it's a reasonable
    // size that is large enough for all purposes but not too large to choke the change index by
    // exceeding the cumulative comment size limit (new comments are not allowed once the limit
    // is reached). At Google, the change index limit is 5MB, while the cumulative size limit is
    // set at 3MB. In this example, we can reach at most 3.3MB hence we ensure not to exceed the
    // limit of 5MB.
    // The reason we exclude the post submit diff from the cumulative comment size limit is
    // just because change messages not currently being validated. Change messages are still
    // counted towards the limit, though.
    maxCumulativeSize =
        serverConfig.getInt(
            "change",
            "cumulativeCommentSizeLimit",
            CommentCumulativeSizeValidator.DEFAULT_CUMULATIVE_COMMENT_SIZE_LIMIT);
  }

  public String apply(ChangeNotes notes, CurrentUser currentUser)
      throws AuthException, IOException, PermissionBackendException,
          InvalidChangeOperationException {
    PatchSet currentPatchset = notes.getCurrentPatchSet();

    PatchSet.Id latestApprovedPatchsetId = getLatestApprovedPatchsetId(notes);
    if (latestApprovedPatchsetId.get() == currentPatchset.id().get()) {
      // If the latest approved patchset is the current patchset, no need to return anything.
      return "";
    }
    StringBuilder diff =
        new StringBuilder(
            String.format(
                "\n\n%d is the latest approved patch-set.\n", latestApprovedPatchsetId.get()));
    Map<String, FileDiffOutput> modifiedFiles =
        listModifiedFiles(
            notes.getProjectName(),
            currentPatchset,
            notes.getPatchSets().get(latestApprovedPatchsetId));

    // To make the message a bit more concise, we skip the magic files.
    List<FileDiffOutput> modifiedFilesList =
        modifiedFiles.values().stream()
            .filter(p -> !Patch.isMagic(p.newPath().orElse("")))
            .collect(Collectors.toList());

    if (modifiedFilesList.isEmpty()) {
      diff.append(
          "No files were changed between the latest approved patch-set and the submitted one.\n");
      return diff.toString();
    }

    diff.append("The change was submitted with unreviewed changes in the following files:\n\n");
    TemporaryBuffer.Heap buffer =
        new TemporaryBuffer.Heap(
            Math.min(HEAP_EST_SIZE, DEFAULT_POST_SUBMIT_SIZE_LIMIT),
            DEFAULT_POST_SUBMIT_SIZE_LIMIT);
    try (Repository repository = repositoryManager.openRepository(notes.getProjectName());
        DiffFormatter formatter = new DiffFormatter(buffer)) {
      formatter.setRepository(repository);
      formatter.setDetectRenames(true);
      boolean isDiffTooLarge = false;
      List<String> formatterResult = null;
      try {
        formatter.format(
            modifiedFilesList.get(0).oldCommitId(), modifiedFilesList.get(0).newCommitId());
        // This returns the diff for all the files.
        formatterResult =
            Arrays.stream(RawParseUtils.decode(buffer.toByteArray()).split("\n"))
                .collect(Collectors.toList());
      } catch (IOException e) {
        if (JGitText.get().inMemoryBufferLimitExceeded.equals(e.getMessage())) {
          isDiffTooLarge = true;
        } else {
          throw e;
        }
      }
      if (formatterResult != null) {
        int addedBytes = formatterResult.stream().mapToInt(String::length).sum();
        if (!CommentCumulativeSizeValidator.isEnoughSpace(notes, addedBytes, maxCumulativeSize)) {
          isDiffTooLarge = true;
        }
      }
      for (FileDiffOutput fileDiff : modifiedFilesList) {
        diff.append(
            getDiffForFile(
                notes,
                currentPatchset.id(),
                latestApprovedPatchsetId,
                fileDiff,
                currentUser,
                formatterResult,
                isDiffTooLarge));
      }
    }
    return diff.toString();
  }

  private String getDiffForFile(
      ChangeNotes notes,
      PatchSet.Id currentPatchsetId,
      PatchSet.Id latestApprovedPatchsetId,
      FileDiffOutput fileDiffOutput,
      CurrentUser currentUser,
      @Nullable List<String> formatterResult,
      boolean isDiffTooLarge)
      throws AuthException, InvalidChangeOperationException, IOException,
          PermissionBackendException {
    StringBuilder diff =
        new StringBuilder(
            String.format(
                "```\nThe name of the file: %s\nInsertions: %d, Deletions: %d.\n\n",
                fileDiffOutput.newPath().isPresent()
                    ? fileDiffOutput.newPath().get()
                    : fileDiffOutput.oldPath().get(),
                fileDiffOutput.insertions(),
                fileDiffOutput.deletions()));
    DiffPreferencesInfo diffPreferencesInfo = createDefaultDiffPreferencesInfo();
    PatchScriptFactory patchScriptFactory =
        patchScriptFactoryFactory.create(
            notes,
            fileDiffOutput.newPath().isPresent()
                ? fileDiffOutput.newPath().get()
                : fileDiffOutput.oldPath().get(),
            latestApprovedPatchsetId,
            currentPatchsetId,
            diffPreferencesInfo,
            currentUser);
    PatchScript patchScript = null;
    try {
      // TODO(paiking): we can get rid of this call to optimize by checking the diff for renames.
      patchScript = patchScriptFactory.call();
    } catch (LargeObjectException exception) {
      diff.append("The file content is too large for showing the full diff. \n\n");
      return diff.toString();
    }
    if (patchScript.getChangeType() == ChangeType.RENAMED) {
      diff.append(
          String.format(
              "The file %s was renamed to %s\n",
              fileDiffOutput.oldPath().get(), fileDiffOutput.newPath().get()));
    }
    if (isDiffTooLarge) {
      diff.append("The diff is too large to show. Please review the diff.");
      diff.append("\n```\n");
      return diff.toString();
    }
    // This filters only the file we need.
    // TODO(paiking): we can make this more efficient by mapping the files to their respective
    //  diffs prior to this method, such that we need to go over the diff only once.
    diff.append(getDiffForFile(patchScript, formatterResult));
    // This line (and the ``` above) are useful for formatting in the web UI.
    diff.append("\n```\n");
    return diff.toString();
  }

  /**
   * Show patch set as unified difference for a specific file. We on purpose are not using {@link
   * DiffInfoCreator} since we'd like to get the original git/JGit style diff.
   */
  public String getDiffForFile(PatchScript patchScript, List<String> formatterResult) {
    // only return information about the current file, and not about files that are not
    // relevant. DiffFormatter returns other potential files because of rebases, which we can
    // ignore.
    List<String> modifiedFormatterResult = new ArrayList<>();
    int indexOfFormatterResult = 0;
    while (formatterResult.size() > indexOfFormatterResult
        && !formatterResult
            .get(indexOfFormatterResult)
            .equals(
                String.format(
                    "diff --git a/%s b/%s",
                    patchScript.getOldName() != null
                        ? patchScript.getOldName()
                        : patchScript.getNewName(),
                    patchScript.getNewName()))) {
      indexOfFormatterResult++;
    }
    // remove non user friendly information.
    while (formatterResult.size() > indexOfFormatterResult
        && !formatterResult.get(indexOfFormatterResult).startsWith("@@")) {
      indexOfFormatterResult++;
    }
    for (; indexOfFormatterResult < formatterResult.size(); indexOfFormatterResult++) {
      if (formatterResult.get(indexOfFormatterResult).startsWith("diff --git")) {
        break;
      }
      modifiedFormatterResult.add(formatterResult.get(indexOfFormatterResult));
    }
    if (modifiedFormatterResult.size() == 0) {
      // This happens for diffs that are just renames, but we already account for renames.
      return "";
    }
    return modifiedFormatterResult.stream()
        .filter(s -> !s.equals("\\ No newline at end of file"))
        .collect(Collectors.joining("\n"));
  }

  private DiffPreferencesInfo createDefaultDiffPreferencesInfo() {
    DiffPreferencesInfo diffPreferencesInfo = new DiffPreferencesInfo();
    diffPreferencesInfo.ignoreWhitespace = Whitespace.IGNORE_NONE;
    diffPreferencesInfo.intralineDifference = true;
    return diffPreferencesInfo;
  }

  private PatchSet.Id getLatestApprovedPatchsetId(ChangeNotes notes) {
    ProjectState projectState =
        projectCache.get(notes.getProjectName()).orElseThrow(illegalState(notes.getProjectName()));
    PatchSet.Id maxPatchSetId = PatchSet.id(notes.getChangeId(), 1);
    for (PatchSetApproval patchSetApproval : notes.getApprovals().values()) {
      if (!patchSetApproval.label().equals(LabelId.CODE_REVIEW)) {
        continue;
      }
      Optional<LabelType> lt =
          projectState.getLabelTypes(notes).byLabel(patchSetApproval.labelId());
      if (!lt.isPresent() || !lt.get().isMaxPositive(patchSetApproval)) {
        continue;
      }
      if (patchSetApproval.patchSetId().get() > maxPatchSetId.get()) {
        maxPatchSetId = patchSetApproval.patchSetId();
      }
    }
    return maxPatchSetId;
  }

  /**
   * Gets the list of modified files between the two latest patch-sets. Can be used to compute
   * difference in files between those two patch-sets.
   */
  private Map<String, FileDiffOutput> listModifiedFiles(
      Project.NameKey project, PatchSet ps, PatchSet priorPatchSet) {
    try {
      return diffOperations.listModifiedFiles(
          project, priorPatchSet.commitId(), ps.commitId(), DiffOptions.DEFAULTS);
    } catch (DiffNotAvailableException ex) {
      throw new StorageException(
          "failed to compute difference in files, so won't post diff messsage on submit although "
              + "the latest approved patch-set was not the same as the submitted patch-set.",
          ex);
    }
  }
}
