// Copyright (C) 2011 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.account;

import com.google.gerrit.common.errors.NameAlreadyUsedException;
import com.google.gerrit.common.errors.PermissionDeniedException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.AccountGroupIncludeByUuid;
import com.google.gerrit.reviewdb.client.AccountGroupIncludeByUuidAudit;
import com.google.gerrit.reviewdb.client.AccountGroupMember;
import com.google.gerrit.reviewdb.client.AccountGroupMemberAudit;
import com.google.gerrit.reviewdb.client.AccountGroupName;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gwtorm.server.OrmDuplicateKeyException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;

import org.eclipse.jgit.lib.PersonIdent;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class PerformCreateGroup {

  public interface Factory {
    PerformCreateGroup create();
  }

  private final ReviewDb db;
  private final AccountCache accountCache;
  private final GroupIncludeCache groupIncludeCache;
  private final IdentifiedUser currentUser;
  private final PersonIdent serverIdent;
  private final GroupCache groupCache;

  @Inject
  PerformCreateGroup(final ReviewDb db, final AccountCache accountCache,
      final GroupIncludeCache groupIncludeCache,
      final IdentifiedUser currentUser,
      @GerritPersonIdent final PersonIdent serverIdent,
      final GroupCache groupCache) {
    this.db = db;
    this.accountCache = accountCache;
    this.groupIncludeCache = groupIncludeCache;
    this.currentUser = currentUser;
    this.serverIdent = serverIdent;
    this.groupCache = groupCache;
  }

  /**
   * Creates a new group.
   *
   * @param groupName the name for the new group
   * @param groupDescription the description of the new group, <code>null</code>
   *        if no description
   * @param visibleToAll <code>true</code> to make the group visible to all
   *        registered users, if <code>false</code> the group is only visible to
   *        the group owners and Gerrit administrators
   * @param ownerGroupId the group that should own the new group, if
   *        <code>null</code> the new group will own itself
   * @param initialMembers initial members to be added to the new group
   * @param initialGroups initial groups to include in the new group
   * @return the id of the new group
   * @throws OrmException is thrown in case of any data store read or write
   *         error
   * @throws NameAlreadyUsedException is thrown in case a group with the given
   *         name already exists
   * @throws PermissionDeniedException user cannot create a group.
   */
  public AccountGroup createGroup(final String groupName,
      final String groupDescription, final boolean visibleToAll,
      final AccountGroup.Id ownerGroupId,
      final Collection<? extends Account.Id> initialMembers,
      final Collection<? extends AccountGroup.UUID> initialGroups)
      throws OrmException, NameAlreadyUsedException, PermissionDeniedException {
    if (!currentUser.getCapabilities().canCreateGroup()) {
      throw new PermissionDeniedException(String.format(
        "%s does not have \"Create Group\" capability.",
        currentUser.getUserName()));
    }

    final AccountGroup.Id groupId =
        new AccountGroup.Id(db.nextAccountGroupId());
    final AccountGroup.NameKey nameKey = new AccountGroup.NameKey(groupName);
    final AccountGroup.UUID uuid = GroupUUID.make(groupName,
        currentUser.newCommitterIdent(
            serverIdent.getWhen(),
            serverIdent.getTimeZone()));
    final AccountGroup group = new AccountGroup(nameKey, groupId, uuid);
    group.setVisibleToAll(visibleToAll);
    if (ownerGroupId != null) {
      AccountGroup ownerGroup = groupCache.get(ownerGroupId);
      if (ownerGroup != null) {
        group.setOwnerGroupUUID(ownerGroup.getGroupUUID());
      }
    }
    if (groupDescription != null) {
      group.setDescription(groupDescription);
    }
    final AccountGroupName gn = new AccountGroupName(group);
    // first insert the group name to validate that the group name hasn't
    // already been used to create another group
    try {
      db.accountGroupNames().insert(Collections.singleton(gn));
    } catch (OrmDuplicateKeyException e) {
      throw new NameAlreadyUsedException(groupName);
    }
    db.accountGroups().insert(Collections.singleton(group));

    addMembers(groupId, initialMembers);

    if (initialGroups != null) {
      addGroups(groupId, initialGroups);
      groupIncludeCache.evictMembersOf(uuid);
    }

    groupCache.onCreateGroup(nameKey);

    return group;
  }

  private void addMembers(final AccountGroup.Id groupId,
      final Collection<? extends Account.Id> members) throws OrmException {
    final List<AccountGroupMember> memberships =
        new ArrayList<AccountGroupMember>();
    final List<AccountGroupMemberAudit> membershipsAudit =
        new ArrayList<AccountGroupMemberAudit>();
    for (Account.Id accountId : members) {
      final AccountGroupMember membership =
          new AccountGroupMember(new AccountGroupMember.Key(accountId, groupId));
      memberships.add(membership);

      final AccountGroupMemberAudit audit =
          new AccountGroupMemberAudit(membership, currentUser.getAccountId());
      membershipsAudit.add(audit);
    }
    db.accountGroupMembers().insert(memberships);
    db.accountGroupMembersAudit().insert(membershipsAudit);

    for (Account.Id accountId : members) {
      accountCache.evict(accountId);
    }
  }

  private void addGroups(final AccountGroup.Id groupId,
      final Collection<? extends AccountGroup.UUID> groups) throws OrmException {
    final List<AccountGroupIncludeByUuid> includeList =
      new ArrayList<AccountGroupIncludeByUuid>();
    final List<AccountGroupIncludeByUuidAudit> includesAudit =
      new ArrayList<AccountGroupIncludeByUuidAudit>();
    for (AccountGroup.UUID includeUUID : groups) {
      final AccountGroupIncludeByUuid groupInclude =
        new AccountGroupIncludeByUuid(new AccountGroupIncludeByUuid.Key(groupId, includeUUID));
      includeList.add(groupInclude);

      final AccountGroupIncludeByUuidAudit audit =
        new AccountGroupIncludeByUuidAudit(groupInclude, currentUser.getAccountId());
      includesAudit.add(audit);
    }
    db.accountGroupIncludesByUuid().insert(includeList);
    db.accountGroupIncludesByUuidAudit().insert(includesAudit);

    for (AccountGroup.UUID uuid : groups) {
      groupIncludeCache.evictMemberIn(uuid);
    }
  }
}
