// Copyright (C) 2018 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.change;

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

import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Address;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Project;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.config.SendEmailExecutor;
import com.google.gerrit.server.mail.EmailModule.StartReviewChangeEmailFactories;
import com.google.gerrit.server.mail.send.ChangeEmail;
import com.google.gerrit.server.mail.send.MessageIdGenerator;
import com.google.gerrit.server.mail.send.OutgoingEmail;
import com.google.gerrit.server.mail.send.StartReviewChangeEmailDecorator;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.Collection;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

@Singleton
public class ModifyReviewersEmail {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final StartReviewChangeEmailFactories startReviewChangeEmailFactories;
  private final ExecutorService sendEmailsExecutor;
  private final MessageIdGenerator messageIdGenerator;

  @Inject
  ModifyReviewersEmail(
      StartReviewChangeEmailFactories startReviewChangeEmailFactories,
      @SendEmailExecutor ExecutorService sendEmailsExecutor,
      MessageIdGenerator messageIdGenerator) {
    this.startReviewChangeEmailFactories = startReviewChangeEmailFactories;
    this.sendEmailsExecutor = sendEmailsExecutor;
    this.messageIdGenerator = messageIdGenerator;
  }

  public void emailReviewersAsync(
      IdentifiedUser user,
      Change change,
      Collection<Account.Id> added,
      Collection<Account.Id> copied,
      Collection<Account.Id> removed,
      Collection<Address> addedByEmail,
      Collection<Address> copiedByEmail,
      Collection<Address> removedByEmail,
      NotifyResolver.Result notify) {
    // The user knows they added/removed themselves, don't bother emailing them.
    Account.Id userId = user.getAccountId();
    ImmutableList<Account.Id> immutableToMail =
        added.stream().filter(id -> !id.equals(userId)).collect(toImmutableList());
    ImmutableList<Account.Id> immutableToCopy =
        copied.stream().filter(id -> !id.equals(userId)).collect(toImmutableList());
    ImmutableList<Account.Id> immutableToRemove =
        removed.stream().filter(id -> !id.equals(userId)).collect(toImmutableList());
    if (immutableToMail.isEmpty()
        && immutableToCopy.isEmpty()
        && immutableToRemove.isEmpty()
        && addedByEmail.isEmpty()
        && copiedByEmail.isEmpty()
        && removedByEmail.isEmpty()) {
      return;
    }

    // Make immutable copies of collections and hand over only immutable data types to the other
    // thread.
    Change.Id cId = change.getId();
    Project.NameKey projectNameKey = change.getProject();
    ImmutableList<Address> immutableAddedByEmail = ImmutableList.copyOf(addedByEmail);
    ImmutableList<Address> immutableCopiedByEmail = ImmutableList.copyOf(copiedByEmail);
    ImmutableList<Address> immutableRemovedByEmail = ImmutableList.copyOf(removedByEmail);

    @SuppressWarnings("unused")
    Future<?> possiblyIgnoredError =
        sendEmailsExecutor.submit(
            () -> {
              try {
                StartReviewChangeEmailDecorator startReviewEmail =
                    startReviewChangeEmailFactories.createStartReviewChangeEmail();
                startReviewEmail.addReviewers(immutableToMail);
                startReviewEmail.addReviewersByEmail(immutableAddedByEmail);
                startReviewEmail.addExtraCC(immutableToCopy);
                startReviewEmail.addExtraCCByEmail(immutableCopiedByEmail);
                startReviewEmail.addRemovedReviewers(immutableToRemove);
                startReviewEmail.addRemovedByEmailReviewers(immutableRemovedByEmail);
                ChangeEmail changeEmail =
                    startReviewChangeEmailFactories.createChangeEmail(
                        projectNameKey, cId, startReviewEmail);
                OutgoingEmail outgoingEmail =
                    startReviewChangeEmailFactories.createEmail(changeEmail);
                outgoingEmail.setNotify(notify);
                outgoingEmail.setFrom(userId);
                outgoingEmail.setMessageId(
                    messageIdGenerator.fromChangeUpdate(
                        change.getProject(), change.currentPatchSetId()));
                outgoingEmail.send();
              } catch (Exception err) {
                logger.atSevere().withCause(err).log(
                    "Cannot send email to new reviewers of change %s", change.getId());
              }
            });
  }
}
