// 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.googlesource.gerrit.plugins.reviewers;

import static java.util.stream.Collectors.toSet;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Sets;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.account.GroupMembers;
import com.google.gerrit.server.group.GroupsCollection;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/* Resolve account and group names to account ids */
@Singleton
class ReviewersResolver {
  private static final Logger log = LoggerFactory.getLogger(ReviewersResolver.class);

  private final AccountResolver accountResolver;
  private final Provider<GroupsCollection> groupsCollection;
  private final GroupMembers.Factory groupMembersFactory;
  private final IdentifiedUser.GenericFactory identifiedUserFactory;

  @Inject
  ReviewersResolver(
      AccountResolver accountResolver,
      Provider<GroupsCollection> groupsCollection,
      GroupMembers.Factory groupMembersFactory,
      IdentifiedUser.GenericFactory identifiedUserFactory) {
    this.accountResolver = accountResolver;
    this.groupsCollection = groupsCollection;
    this.groupMembersFactory = groupMembersFactory;
    this.identifiedUserFactory = identifiedUserFactory;
  }

  /**
   * Resolve a set of account names to {@link com.google.gerrit.reviewdb.client.Account.Id}s. Group
   * names are resolved to their account members.
   *
   * @param reviewDb DB
   * @param names the set of account names to convert
   * @param project the project name
   * @param changeNumber the change Id
   * @param uploader account to use to look up groups, or null if groups are not needed
   * @return set of {@link com.google.gerrit.reviewdb.client.Account.Id}s.
   */
  @VisibleForTesting
  Set<Account.Id> resolve(
      ReviewDb reviewDb,
      Set<String> names,
      Project.NameKey project,
      int changeNumber,
      @Nullable AccountInfo uploader) {
    Set<Account.Id> reviewers = Sets.newHashSetWithExpectedSize(names.size());
    GroupMembers groupMembers = null;
    for (String name : names) {
      if (resolveAccount(reviewDb, project, changeNumber, uploader, reviewers, name)) {
        continue;
      }

      if (groupMembers == null && uploader != null) {
        groupMembers = createGroupMembers(reviewDb, project, changeNumber, uploader, name);
      }

      if (groupMembers != null) {
        resolveGroup(project, changeNumber, reviewers, groupMembers, name);
      } else {
        log.warn(
            "For the change {} of project {}: failed to list accounts for group {}; cannot retrieve uploader account for {}.",
            changeNumber,
            project,
            name,
            uploader.email);
      }
    }
    return reviewers;
  }

  private boolean resolveAccount(
      ReviewDb reviewDb,
      Project.NameKey project,
      int changeNumber,
      AccountInfo uploader,
      Set<Account.Id> reviewers,
      String accountName) {
    try {
      Account account = accountResolver.find(reviewDb, accountName);
      if (account != null) {
        if (account.isActive()) {
          if (uploader == null || uploader._accountId != account.getId().get()) {
            reviewers.add(account.getId());
          }
          return true;
        }
        log.warn(
            "For the change {} of project {}: account {} is inactive.",
            changeNumber,
            project,
            accountName);
      }
    } catch (OrmException e) {
      // If the account doesn't exist, find() will return null.  We only
      // get here if something went wrong accessing the database
      log.error(
          "For the change {} of project {}: failed to resolve account {}.",
          changeNumber,
          project,
          accountName,
          e);
      return true;
    }
    return false;
  }

  private void resolveGroup(
      Project.NameKey project,
      int changeNumber,
      Set<Account.Id> reviewers,
      GroupMembers groupMembers,
      String group) {
    try {
      Set<Account.Id> accounts =
          groupMembers
              .listAccounts(groupsCollection.get().parse(group).getGroupUUID(), project)
              .stream()
              .filter(Account::isActive)
              .map(Account::getId)
              .collect(toSet());
      reviewers.addAll(accounts);
    } catch (UnprocessableEntityException | NoSuchGroupException e) {
      log.warn(
          "For the change {} of project {}: reviewer {} is neither an account nor a group.",
          changeNumber,
          project,
          group,
          e);
    } catch (NoSuchProjectException | IOException | OrmException e) {
      log.warn(
          "For the change {} of project {}: failed to list accounts for group {}.",
          changeNumber,
          project,
          group,
          e);
    }
  }

  private GroupMembers createGroupMembers(
      ReviewDb reviewDb,
      Project.NameKey project,
      int changeNumber,
      AccountInfo uploader,
      String group) {
    // email is not unique to one account, try to locate the account using
    // "Full name <email>" to increase chance of finding only one.
    String uploaderNameEmail = String.format("%s <%s>", uploader.name, uploader.email);
    try {
      Account uploaderAccount = accountResolver.findByNameOrEmail(reviewDb, uploaderNameEmail);
      if (uploaderAccount != null) {
        return groupMembersFactory.create(identifiedUserFactory.create(uploaderAccount.getId()));
      }
    } catch (OrmException e) {
      log.warn(
          "For the change {} of project {}: failed to list accounts for group {}, cannot retrieve uploader account {}.",
          changeNumber,
          project,
          group,
          uploaderNameEmail,
          e);
    }
    return null;
  }
}
