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

import static com.google.common.collect.ImmutableList.toImmutableList;
import static java.util.Comparator.comparing;
import static java.util.Objects.requireNonNull;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.extensions.common.ChangeType;
import com.google.gerrit.plugins.codeowners.JgitPath;
import com.google.gerrit.plugins.codeowners.api.CodeOwnerStatusInfo;
import com.google.gerrit.plugins.codeowners.api.FileCodeOwnerStatusInfo;
import com.google.gerrit.plugins.codeowners.api.PathCodeOwnerStatusInfo;
import com.google.gerrit.plugins.codeowners.backend.FileCodeOwnerStatus;
import com.google.gerrit.plugins.codeowners.backend.PathCodeOwnerStatus;
import java.util.Comparator;
import org.eclipse.jgit.diff.DiffEntry;

/** Collection of routines to populate {@link CodeOwnerStatusInfo}. */
public class CodeOwnerStatusInfoJson {
  /** Comparator that sorts {@link FileCodeOwnerStatus} by new path and then old path. */
  private static final Comparator<FileCodeOwnerStatus> FILE_CODE_OWNER_STATUS_COMPARATOR =
      comparing(
          (FileCodeOwnerStatus fileStatus) -> {
            if (fileStatus.newPathStatus().isPresent()) {
              return fileStatus.newPathStatus().get().path().toString();
            }
            if (fileStatus.oldPathStatus().isPresent()) {
              return fileStatus.oldPathStatus().get().path().toString();
            }
            throw new IllegalStateException(
                String.format(
                    "file code owner status %s has neither oldPath nor newPath", fileStatus));
          });

  private static final ImmutableMap<DiffEntry.ChangeType, ChangeType> CHANGE_TYPE =
      Maps.immutableEnumMap(
          new ImmutableMap.Builder<DiffEntry.ChangeType, ChangeType>()
              .put(DiffEntry.ChangeType.ADD, ChangeType.ADDED)
              .put(DiffEntry.ChangeType.MODIFY, ChangeType.MODIFIED)
              .put(DiffEntry.ChangeType.DELETE, ChangeType.DELETED)
              .put(DiffEntry.ChangeType.RENAME, ChangeType.RENAMED)
              .put(DiffEntry.ChangeType.COPY, ChangeType.COPIED)
              .build());

  /**
   * Formats a {@link CodeOwnerStatusInfo} from the provided file code owner statuses.
   *
   * @param patchSetId the ID of the patch set for which the file code owner statuses were computed
   * @param fileCodeOwnerStatuses the {@link FileCodeOwnerStatus}es that should be set in the {@link
   *     CodeOwnerStatusInfo}
   * @return the created {@link CodeOwnerStatusInfo}
   */
  public static CodeOwnerStatusInfo format(
      PatchSet.Id patchSetId, ImmutableSet<FileCodeOwnerStatus> fileCodeOwnerStatuses) {
    requireNonNull(patchSetId, "patchSetId");
    requireNonNull(fileCodeOwnerStatuses, "fileCodeOwnerStatuses");
    CodeOwnerStatusInfo info = new CodeOwnerStatusInfo();
    info.patchSetNumber = patchSetId.get();
    info.fileCodeOwnerStatuses =
        fileCodeOwnerStatuses.stream()
            .sorted(FILE_CODE_OWNER_STATUS_COMPARATOR)
            .map(CodeOwnerStatusInfoJson::format)
            .collect(toImmutableList());
    return info;
  }

  /**
   * Formats the provided {@link FileCodeOwnerStatus} as {@link FileCodeOwnerStatusInfo}.
   *
   * @param fileCodeOwnerStatus the {@link FileCodeOwnerStatus} that should be formatted as {@link
   *     FileCodeOwnerStatusInfo}
   * @return the provided {@link FileCodeOwnerStatus} as {@link FileCodeOwnerStatusInfo}
   */
  @VisibleForTesting
  static FileCodeOwnerStatusInfo format(FileCodeOwnerStatus fileCodeOwnerStatus) {
    requireNonNull(fileCodeOwnerStatus, "fileCodeOwnerStatus");
    FileCodeOwnerStatusInfo info = new FileCodeOwnerStatusInfo();
    info.changeType =
        fileCodeOwnerStatus.changedFile().changeType() != DiffEntry.ChangeType.MODIFY
            ? CHANGE_TYPE.get(fileCodeOwnerStatus.changedFile().changeType())
            : null;
    fileCodeOwnerStatus
        .oldPathStatus()
        .ifPresent(oldPathStatus -> info.oldPathStatus = format(oldPathStatus));
    fileCodeOwnerStatus
        .newPathStatus()
        .ifPresent(newPathStatus -> info.newPathStatus = format(newPathStatus));
    return info;
  }

  /**
   * Formats the provided {@link PathCodeOwnerStatus} as {@link PathCodeOwnerStatusInfo}.
   *
   * @param pathCodeOwnerStatus the {@link PathCodeOwnerStatus} that should be formatted as {@link
   *     PathCodeOwnerStatusInfo}
   * @return the provided {@link PathCodeOwnerStatus} as {@link PathCodeOwnerStatusInfo}
   */
  @VisibleForTesting
  static PathCodeOwnerStatusInfo format(PathCodeOwnerStatus pathCodeOwnerStatus) {
    requireNonNull(pathCodeOwnerStatus, "pathCodeOwnerStatus");
    PathCodeOwnerStatusInfo info = new PathCodeOwnerStatusInfo();
    info.path = JgitPath.of(pathCodeOwnerStatus.path()).get();
    info.status = pathCodeOwnerStatus.status();
    return info;
  }

  /**
   * Private constructor to prevent instantiation of this class.
   *
   * <p>The class only contains static methods, hence the class never needs to be instantiated.
   */
  private CodeOwnerStatusInfoJson() {}
}
