// 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.plugins.codeowners.backend;

import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Patch;
import com.google.gerrit.plugins.codeowners.util.JgitPath;
import com.google.gerrit.server.patch.PatchListEntry;
import java.nio.file.Path;
import java.util.Optional;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;

/**
 * A file that was touched in a change.
 *
 * <p>Wrapper around {@link DiffEntry} that provides convenience methods to access data from {@link
 * DiffEntry} and hides data that is not relevant for the code owners plugin.
 */
@AutoValue
public abstract class ChangedFile {
  private static final ImmutableMap<Patch.ChangeType, ChangeType> CHANGE_TYPE =
      Maps.immutableEnumMap(
          new ImmutableMap.Builder<Patch.ChangeType, ChangeType>()
              .put(Patch.ChangeType.ADDED, ChangeType.ADD)
              .put(Patch.ChangeType.MODIFIED, ChangeType.MODIFY)
              .put(Patch.ChangeType.DELETED, ChangeType.DELETE)
              .put(Patch.ChangeType.RENAMED, ChangeType.RENAME)
              .put(Patch.ChangeType.COPIED, ChangeType.COPY)
              .put(Patch.ChangeType.REWRITE, ChangeType.MODIFY)
              .build());

  /**
   * The new path of the file.
   *
   * <p>Not set if the file was deleted.
   *
   * <p>If set, the new path is returned as absolute path.
   */
  public abstract Optional<Path> newPath();

  /**
   * The old path of the file.
   *
   * <p>Not set if the file was newly added
   *
   * <p>If set, the old path is returned as absolute path.
   */
  public abstract Optional<Path> oldPath();

  /** Gets the change type. */
  public abstract ChangeType changeType();

  /**
   * Whether the file has the given path as new path.
   *
   * @param absolutePath an absolute path for which it should be checked if it matches the new path
   *     of this file
   */
  public boolean hasNewPath(Path absolutePath) {
    requireNonNull(absolutePath, "absolutePath");
    checkState(absolutePath.isAbsolute(), "path %s must be absolute", absolutePath);
    return newPath().isPresent() && newPath().get().equals(absolutePath);
  }

  /**
   * Whether the file has the given path as old path.
   *
   * @param absolutePath an absolute path for which it should be checked if it matches the old path
   *     of this file
   */
  public boolean hasOldPath(Path absolutePath) {
    requireNonNull(absolutePath, "absolutePath");
    checkState(absolutePath.isAbsolute(), "path %s must be absolute", absolutePath);
    return oldPath().isPresent() && oldPath().get().equals(absolutePath);
  }

  /** Whether the file was renamed. */
  public boolean isRename() {
    return changeType() == ChangeType.RENAME;
  }

  /** Whether the file was deleted. */
  public boolean isDeletion() {
    return changeType() == ChangeType.DELETE;
  }

  /**
   * Creates a {@link ChangedFile} instance from a {@link DiffEntry}.
   *
   * @param diffEntry the diff entry
   */
  public static ChangedFile create(DiffEntry diffEntry) {
    requireNonNull(diffEntry, "diffEntry");
    return new AutoValue_ChangedFile(
        convertPathFromDiffEntryPath(diffEntry.getNewPath()),
        convertPathFromDiffEntryPath(diffEntry.getOldPath()),
        diffEntry.getChangeType());
  }

  /**
   * Converts the given string path to an absolute path.
   *
   * <p>{@link DiffEntry} is using {@code /dev/null} if a path doesn't exist. If the given path is
   * {@code /dev/null} {@link Optional#empty} is returned.
   */
  private static Optional<Path> convertPathFromDiffEntryPath(String path) {
    if (DiffEntry.DEV_NULL.equals(path)) {
      return Optional.empty();
    }
    return Optional.of(JgitPath.of(path).getAsAbsolutePath());
  }

  /**
   * Creates a {@link ChangedFile} instance from a {@link PatchListEntry}.
   *
   * @param patchListEntry the patch list entry
   */
  public static ChangedFile create(PatchListEntry patchListEntry) {
    requireNonNull(patchListEntry, "patchListEntry");

    if (patchListEntry.getChangeType() == Patch.ChangeType.DELETED) {
      // For deletions PatchListEntry sets the old path as new name and the old name is unset (see
      // PatchListEntry constructor). This means to get the old path we need to read the new name.
      return new AutoValue_ChangedFile(
          Optional.empty(),
          convertPathFromPatchListEntry(patchListEntry.getNewName()),
          CHANGE_TYPE.get(patchListEntry.getChangeType()));
    }

    return new AutoValue_ChangedFile(
        convertPathFromPatchListEntry(patchListEntry.getNewName()),
        convertPathFromPatchListEntry(patchListEntry.getOldName()),
        CHANGE_TYPE.get(patchListEntry.getChangeType()));
  }

  /**
   * Converts the given string path to an absolute path.
   *
   * <p>{@link PatchListEntry} is using {@code null} if a path doesn't exist. If the given path is
   * {@code null} {@link Optional#empty} is returned.
   */
  private static Optional<Path> convertPathFromPatchListEntry(@Nullable String path) {
    return Optional.ofNullable(path).map(newName -> JgitPath.of(newName).getAsAbsolutePath());
  }
}
