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

import static com.google.gerrit.server.notedb.ReviewerStateInternal.REVIEWER;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;

import com.google.gerrit.entities.Account;
import com.google.gerrit.extensions.api.changes.AttentionSetInput;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.change.AddToAttentionSetOp;
import com.google.gerrit.server.change.AttentionSetUnchangedOp;
import com.google.gerrit.server.change.RemoveFromAttentionSetOp;
import com.google.gerrit.server.change.ReviewerAdder;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.permissions.ChangePermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.util.AttentionSetUtil;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;

/**
 * This class is used by {@link PostReview} to update the attention set when performing a review.
 */
public class PostReviewAttentionSet {

  private final PermissionBackend permissionBackend;
  private final AddToAttentionSetOp.Factory addToAttentionSetOpFactory;
  private final RemoveFromAttentionSetOp.Factory removeFromAttentionSetOpFactory;
  private final ApprovalsUtil approvalsUtil;
  private final AccountResolver accountResolver;

  @Inject
  PostReviewAttentionSet(
      PermissionBackend permissionBackend,
      AddToAttentionSetOp.Factory addToAttentionSetOpFactory,
      RemoveFromAttentionSetOp.Factory removeFromAttentionSetOpFactory,
      ApprovalsUtil approvalsUtil,
      AccountResolver accountResolver) {
    this.permissionBackend = permissionBackend;
    this.addToAttentionSetOpFactory = addToAttentionSetOpFactory;
    this.removeFromAttentionSetOpFactory = removeFromAttentionSetOpFactory;
    this.approvalsUtil = approvalsUtil;
    this.accountResolver = accountResolver;
  }

  /**
   * Adjusts the attention set by adding and removing users. If the same user should be added and
   * removed or added/removed twice, the user will only be added/removed once, based on first
   * addition/removal.
   */
  public void updateAttentionSet(
      BatchUpdate bu,
      RevisionResource revision,
      ReviewInput input,
      List<ReviewerAdder.ReviewerAddition> reviewerResults)
      throws BadRequestException, IOException, PermissionBackendException,
          UnprocessableEntityException, ConfigInvalidException {
    processManualUpdates(bu, revision, input);
    if (input.ignoreDefaultAttentionSetRules) {

      // If We ignore default attention set rules it means we need to pass this information to
      // ChangeUpdate. Also, we should stop all other attention set update that are part of
      // this method (that happen in PostReview.
      bu.addOp(revision.getChange().getId(), new AttentionSetUnchangedOp());
      return;
    }
    processRules(bu, revision, input, reviewerResults);
  }

  /**
   * Process the default rules of the attention set. All of the default rules except adding/removing
   * reviewers and entering/exiting WIP state are done here, and the rest are done in {@link
   * ChangeUpdate}
   */
  private void processRules(
      BatchUpdate bu,
      RevisionResource revision,
      ReviewInput input,
      List<ReviewerAdder.ReviewerAddition> reviewerResults) {
    // Replying removes the publishing user from the attention set.
    RemoveFromAttentionSetOp removeFromAttentionSetOp =
        removeFromAttentionSetOpFactory.create(revision.getAccountId(), "removed on reply");
    bu.addOp(revision.getChange().getId(), removeFromAttentionSetOp);

    // The rest of the conditions only apply if the change is ready for review
    if (!isReadyForReview(revision, input)) {
      return;
    }
    Account.Id uploader = revision.getPatchSet().uploader();
    Account.Id owner = revision.getChange().getOwner();
    Account.Id currentUser = revision.getAccountId();
    if (currentUser.equals(uploader) && !uploader.equals(owner)) {
      // When the uploader replies, add the owner to the attention set.
      AddToAttentionSetOp addToAttentionSetOp =
          addToAttentionSetOpFactory.create(owner, "uploader replied");
      bu.addOp(revision.getChange().getId(), addToAttentionSetOp);
    }
    if (currentUser.equals(uploader) || currentUser.equals(owner)) {
      // When the owner or uploader replies, add the reviewers to the attention set.
      // Filter by users that are currently reviewers.
      Set<Account.Id> finalCCs =
          reviewerResults.stream()
              .filter(r -> r.result.ccs == null)
              .map(r -> r.reviewers)
              .flatMap(x -> x.stream())
              .collect(toSet());
      for (Account.Id reviewer :
          approvalsUtil.getReviewers(revision.getChangeResource().getNotes()).byState(REVIEWER)
              .stream()
              .filter(r -> !finalCCs.contains(r))
              .collect(toList())) {
        AddToAttentionSetOp addToAttentionSetOp =
            addToAttentionSetOpFactory.create(reviewer, "owner or uploader replied");
        bu.addOp(revision.getChange().getId(), addToAttentionSetOp);
      }
    }
    if (!currentUser.equals(uploader) && !currentUser.equals(owner)) {
      // When neither the uploader nor the owner (reviewer or cc) replies, add the owner and the
      // uploader to the attention set.
      AddToAttentionSetOp addToAttentionSetOp =
          addToAttentionSetOpFactory.create(owner, "reviewer or cc replied");
      bu.addOp(revision.getChange().getId(), addToAttentionSetOp);

      if (owner.get() != uploader.get()) {
        addToAttentionSetOp = addToAttentionSetOpFactory.create(uploader, "reviewer or cc replied");
        bu.addOp(revision.getChange().getId(), addToAttentionSetOp);
      }
    }
  }

  /** Process the manual updates of the attention set. */
  private void processManualUpdates(BatchUpdate bu, RevisionResource revision, ReviewInput input)
      throws BadRequestException, IOException, PermissionBackendException,
          UnprocessableEntityException, ConfigInvalidException {
    Set<Account.Id> accountsChangedInCommit = new HashSet();
    // If we specify a user to remove, and the user is in the attention set, we remove it.
    if (input.removeFromAttentionSet != null) {
      for (AttentionSetInput remove : input.removeFromAttentionSet) {
        removeFromAttentionSet(bu, revision, remove, accountsChangedInCommit);
      }
    }

    // If we don't specify a user to remove, but we specify addition for that user, the user will be
    // added if they are not in the attention set yet.
    if (input.addToAttentionSet != null) {
      for (AttentionSetInput add : input.addToAttentionSet) {
        addToAttentionSet(bu, revision, add, accountsChangedInCommit);
      }
    }
  }

  private static boolean isReadyForReview(RevisionResource revision, ReviewInput input) {
    return (!revision.getChange().isWorkInProgress() && !input.workInProgress) || input.ready;
  }

  private void addToAttentionSet(
      BatchUpdate bu,
      RevisionResource revision,
      AttentionSetInput add,
      Set<Account.Id> accountsChangedInCommitv)
      throws BadRequestException, IOException, PermissionBackendException,
          UnprocessableEntityException, ConfigInvalidException {
    AttentionSetUtil.validateInput(add);
    Account.Id attentionUserId =
        getAccountIdAndValidateUser(revision, add.user, accountsChangedInCommitv);

    AddToAttentionSetOp addToAttentionSetOp =
        addToAttentionSetOpFactory.create(attentionUserId, add.reason);
    bu.addOp(revision.getChange().getId(), addToAttentionSetOp);
  }

  private void removeFromAttentionSet(
      BatchUpdate bu,
      RevisionResource revision,
      AttentionSetInput remove,
      Set<Account.Id> accountsChangedInCommit)
      throws BadRequestException, IOException, PermissionBackendException,
          UnprocessableEntityException, ConfigInvalidException {
    AttentionSetUtil.validateInput(remove);
    Account.Id attentionUserId =
        getAccountIdAndValidateUser(revision, remove.user, accountsChangedInCommit);

    RemoveFromAttentionSetOp removeFromAttentionSetOp =
        removeFromAttentionSetOpFactory.create(attentionUserId, remove.reason);
    bu.addOp(revision.getChange().getId(), removeFromAttentionSetOp);
  }

  private Account.Id getAccountIdAndValidateUser(
      RevisionResource revision, String user, Set<Account.Id> accountsChangedInCommit)
      throws ConfigInvalidException, IOException, PermissionBackendException,
          UnprocessableEntityException, BadRequestException {
    Account.Id attentionUserId = accountResolver.resolve(user).asUnique().account().id();
    try {
      permissionBackend
          .absentUser(attentionUserId)
          .change(revision.getNotes())
          .check(ChangePermission.READ);
    } catch (AuthException e) {
      throw new UnprocessableEntityException(
          "Can't add to attention set: Read not permitted for " + attentionUserId, e);
    }
    if (accountsChangedInCommit.contains(attentionUserId)) {
      throw new BadRequestException(
          String.format(
              "%s can not be added/removed twice, and can not be added and "
                  + "removed at the same time",
              user));
    }
    accountsChangedInCommit.add(attentionUserId);
    return attentionUserId;
  }
}
