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

import static com.google.common.collect.ImmutableList.toImmutableList;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.entities.Account;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.plugins.codeowners.api.OwnedChangedFileInfo;
import com.google.gerrit.plugins.codeowners.api.OwnedPathInfo;
import com.google.gerrit.plugins.codeowners.api.OwnedPathsInfo;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerApprovalCheck;
import com.google.gerrit.plugins.codeowners.backend.OwnedChangedFile;
import com.google.gerrit.plugins.codeowners.backend.OwnedPath;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.account.AccountResolver.UnresolvableAccountException;
import com.google.gerrit.server.change.RevisionResource;
import com.google.inject.Inject;
import java.io.IOException;
import java.nio.file.Path;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.kohsuke.args4j.Option;

/**
 * REST endpoint that lists the files of a revision that are owned by a specified user.
 *
 * <p>This REST endpoint handles {@code GET
 * /changes/<change-id>/revisions/<revision-id>/owned_paths} requests.
 */
public class GetOwnedPaths implements RestReadView<RevisionResource> {
  @VisibleForTesting public static final int DEFAULT_LIMIT = 50;

  private final AccountResolver accountResolver;
  private final CodeOwnerApprovalCheck codeOwnerApprovalCheck;

  private int start;
  private int limit = DEFAULT_LIMIT;
  private String user;

  @Option(
      name = "--limit",
      aliases = {"-n"},
      metaVar = "CNT",
      usage = "maximum number of owned path to return (default = " + DEFAULT_LIMIT + ")")
  public void setLimit(int limit) {
    this.limit = limit;
  }

  @Option(
      name = "--start",
      aliases = {"-S"},
      metaVar = "CNT",
      usage = "number of owned paths to skip")
  public void setStart(int start) {
    this.start = start;
  }

  @Option(name = "--user", usage = "user for which the owned paths should be returned")
  public void setUser(String user) {
    this.user = user;
  }

  @Inject
  public GetOwnedPaths(
      AccountResolver accountResolver, CodeOwnerApprovalCheck codeOwnerApprovalCheck) {
    this.accountResolver = accountResolver;
    this.codeOwnerApprovalCheck = codeOwnerApprovalCheck;
  }

  @Override
  public Response<OwnedPathsInfo> apply(RevisionResource revisionResource)
      throws BadRequestException, ResourceConflictException, UnresolvableAccountException,
          ConfigInvalidException, IOException {
    validateStartAndLimit();

    Account.Id accountId = resolveAccount();

    ImmutableList<OwnedChangedFile> ownedChangedFiles =
        codeOwnerApprovalCheck.getOwnedPaths(
            revisionResource.getNotes(),
            revisionResource.getPatchSet(),
            accountId,
            start,
            limit + 1);

    OwnedPathsInfo ownedPathsInfo = new OwnedPathsInfo();
    ownedPathsInfo.more = ownedChangedFiles.size() > limit ? true : null;
    ownedPathsInfo.ownedChangedFiles =
        ownedChangedFiles.stream()
            .limit(limit)
            .map(GetOwnedPaths::toOwnedChangedFileInfo)
            .collect(toImmutableList());
    ownedPathsInfo.ownedPaths =
        OwnedChangedFile.asPathStream(ownedChangedFiles.stream().limit(limit))
            .map(Path::toString)
            .collect(toImmutableList());
    return Response.ok(ownedPathsInfo);
  }

  private Account.Id resolveAccount()
      throws BadRequestException, UnresolvableAccountException, ConfigInvalidException,
          IOException {
    if (Strings.isNullOrEmpty(user)) {
      throw new BadRequestException("--user required");
    }

    return accountResolver.resolve(user).asUnique().account().id();
  }

  private void validateStartAndLimit() throws BadRequestException {
    if (start < 0) {
      throw new BadRequestException("start cannot be negative");
    }
    if (limit <= 0) {
      throw new BadRequestException("limit must be positive");
    }
  }

  private static OwnedChangedFileInfo toOwnedChangedFileInfo(OwnedChangedFile ownedChangedFile) {
    OwnedChangedFileInfo info = new OwnedChangedFileInfo();
    if (ownedChangedFile.newPath().isPresent()) {
      info.newPath = toOwnedPathInfo(ownedChangedFile.newPath().get());
    }
    if (ownedChangedFile.oldPath().isPresent()) {
      info.oldPath = toOwnedPathInfo(ownedChangedFile.oldPath().get());
    }
    return info;
  }

  private static OwnedPathInfo toOwnedPathInfo(OwnedPath ownedPath) {
    OwnedPathInfo info = new OwnedPathInfo();
    info.path = ownedPath.path().toString();
    info.owned = ownedPath.owned() ? true : null;
    return info;
  }
}
