// Copyright (C) 2024 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.gitdiff;

import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Patch;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.io.DisabledOutputStream;

/**
 * /** Class to load the files that have been modified between two Git trees.
 *
 * <p>Rename detection is off unless {@link #withRenameDetection(int)} is called.
 *
 * <p>The commits and the commit trees are looked up via the {@link RevWalk} instance that is
 * provided to the {@link #load(Config, ObjectReader, ObjectId, ObjectId)} method.
 */
public class GitModifiedFilesLoader {
  private static final ImmutableMap<ChangeType, Patch.ChangeType> changeTypeMap =
      ImmutableMap.of(
          DiffEntry.ChangeType.ADD,
          Patch.ChangeType.ADDED,
          DiffEntry.ChangeType.MODIFY,
          Patch.ChangeType.MODIFIED,
          DiffEntry.ChangeType.DELETE,
          Patch.ChangeType.DELETED,
          DiffEntry.ChangeType.RENAME,
          Patch.ChangeType.RENAMED,
          DiffEntry.ChangeType.COPY,
          Patch.ChangeType.COPIED);

  @Nullable private Integer renameScore = null;

  /**
   * Enables rename detection
   *
   * @param renameScore the score that should be used for the rename detection.
   */
  @CanIgnoreReturnValue
  public GitModifiedFilesLoader withRenameDetection(int renameScore) {
    checkState(renameScore >= 0);
    this.renameScore = renameScore;
    return this;
  }

  /**
   * Loads the files that have been modified between {@code aTree} and {@code bTree}.
   *
   * <p>The trees are looked up via the given {@code revWalk} instance,
   */
  public ImmutableList<ModifiedFile> load(
      Config repoConfig, ObjectReader reader, ObjectId aTree, ObjectId bTree) throws IOException {
    List<DiffEntry> entries = getGitTreeDiff(repoConfig, reader, aTree, bTree);
    return entries.stream().map(GitModifiedFilesLoader::toModifiedFile).collect(toImmutableList());
  }

  private List<DiffEntry> getGitTreeDiff(
      Config repoConfig, ObjectReader reader, ObjectId aTree, ObjectId bTree) throws IOException {
    try (DiffFormatter df = new DiffFormatter(DisabledOutputStream.INSTANCE)) {
      df.setReader(reader, repoConfig);
      if (renameScore != null) {
        df.setDetectRenames(true);
        df.getRenameDetector().setRenameScore(renameScore);

        // Skip detecting content renames for binary files.
        df.getRenameDetector().setSkipContentRenamesForBinaryFiles(true);
      }
      // The scan method only returns the file paths that are different. Callers may choose to
      // format these paths themselves.
      return df.scan(aTree.equals(ObjectId.zeroId()) ? null : aTree, bTree);
    }
  }

  private static ModifiedFile toModifiedFile(DiffEntry entry) {
    String oldPath = entry.getOldPath();
    String newPath = entry.getNewPath();
    return ModifiedFile.builder()
        .changeType(toChangeType(entry.getChangeType()))
        .oldPath(oldPath.equals(DiffEntry.DEV_NULL) ? Optional.empty() : Optional.of(oldPath))
        .newPath(newPath.equals(DiffEntry.DEV_NULL) ? Optional.empty() : Optional.of(newPath))
        .build();
  }

  private static Patch.ChangeType toChangeType(DiffEntry.ChangeType changeType) {
    if (!changeTypeMap.containsKey(changeType)) {
      throw new IllegalArgumentException("Unsupported type " + changeType);
    }
    return changeTypeMap.get(changeType);
  }
}
