// Copyright (C) 2015 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.importer;

import static com.google.gerrit.reviewdb.client.AccountGroup.isInternalGroup;

import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.common.errors.NoSuchAccountException;
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.PreconditionFailedException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.AccountGroupById;
import com.google.gerrit.reviewdb.client.AccountGroupMember;
import com.google.gerrit.reviewdb.client.AccountGroupName;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.CreateGroupArgs;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.account.GroupIncludeCache;
import com.google.gerrit.server.config.ConfigResource;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.group.InternalGroup;
import com.google.gerrit.server.validators.GroupCreationValidationListener;
import com.google.gerrit.server.validators.ValidationException;
import com.google.gwtorm.server.OrmDuplicateKeyException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.googlesource.gerrit.plugins.importer.ImportGroup.Input;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@RequiresCapability(ImportCapability.ID)
class ImportGroup implements RestModifyView<ConfigResource, Input> {
  public static class Input {
    public String from;
    public String user;
    public String pass;
    public boolean importOwnerGroup;
    public boolean importIncludedGroups;
  }

  interface Factory {
    ImportGroup create(AccountGroup.NameKey group);
  }

  private static Logger log = LoggerFactory.getLogger(ImportGroup.class);

  private final Config cfg;
  private final ReviewDb db;
  private final AccountUtil accountUtil;
  private final AccountCache accountCache;
  private final GroupCache groupCache;
  private final GroupIncludeCache groupIncludeCache;
  private final DynamicSet<GroupCreationValidationListener> groupCreationValidationListeners;
  private final ImportGroup.Factory importGroupFactory;
  private final GerritApi.Factory apiFactory;
  private final AccountGroup.NameKey group;
  private GerritApi api;

  @Inject
  ImportGroup(
      @GerritServerConfig Config cfg,
      ReviewDb db,
      AccountUtil accountUtil,
      AccountCache accountCache,
      GroupCache groupCache,
      GroupIncludeCache groupIncludeCache,
      DynamicSet<GroupCreationValidationListener> groupCreationValidationListeners,
      ImportGroup.Factory importGroupFactory,
      GerritApi.Factory apiFactory,
      @Assisted AccountGroup.NameKey group) {
    this.cfg = cfg;
    this.db = db;
    this.accountUtil = accountUtil;
    this.groupCache = groupCache;
    this.accountCache = accountCache;
    this.groupIncludeCache = groupIncludeCache;
    this.groupCreationValidationListeners = groupCreationValidationListeners;
    this.importGroupFactory = importGroupFactory;
    this.apiFactory = apiFactory;
    this.group = group;
  }

  @Override
  public Response<String> apply(ConfigResource rsrc, Input input)
      throws NoSuchAccountException, OrmException, IOException, RestApiException,
          ConfigInvalidException {
    GroupInfo groupInfo;
    this.api = apiFactory.create(input.from, input.user, input.pass);
    groupInfo = api.getGroup(group.get());
    validate(input, groupInfo);
    createGroup(input, groupInfo);

    return Response.ok("OK");
  }

  private void validate(Input input, GroupInfo groupInfo)
      throws IOException, OrmException, NoSuchAccountException, RestApiException,
          ConfigInvalidException {
    if (!isInternalGroup(new AccountGroup.UUID(groupInfo.id))) {
      throw new MethodNotAllowedException(
          String.format(
              "Group with name %s is not an internal group and cannot be imported",
              groupInfo.name));
    }
    if (getGroupByUUID(groupInfo.id) != null) {
      throw new ResourceConflictException(
          String.format("Group with UUID %s already exists", groupInfo.id));
    }
    if (!groupInfo.id.equals(groupInfo.ownerId))
      if (!input.importOwnerGroup && getGroupByUUID(groupInfo.ownerId) == null) {
        throw new PreconditionFailedException(
            String.format(
                "Owner group %s with UUID %s does not exist",
                getGroupName(groupInfo.ownerId), groupInfo.ownerId));
      }
    if (groupInfo.members != null) {
      for (AccountInfo member : groupInfo.members) {
        try {
          accountUtil.resolveUser(api, member);
        } catch (NoSuchAccountException e) {
          throw new PreconditionFailedException(e.getMessage());
        }
      }
    }
    if (!input.importIncludedGroups) {
      if (groupInfo.includes != null) {
        for (GroupInfo include : groupInfo.includes) {
          if (getGroupByUUID(include.id) == null) {
            throw new PreconditionFailedException(
                String.format(
                    "Included group %s with UUID %s does not exist",
                    getGroupName(include.id), include.id));
          }
        }
      }
    }

    for (GroupCreationValidationListener l : groupCreationValidationListeners) {
      try {
        l.validateNewGroup(toCreateGroupArgs(groupInfo));
      } catch (ValidationException e) {
        throw new ResourceConflictException(e.getMessage(), e);
      }
    }
  }

  private Optional<InternalGroup> getGroupByName(String groupName) {
    return groupCache.get(new AccountGroup.NameKey(groupName));
  }

  private Optional<InternalGroup> getGroupByUUID(String uuid) {
    return groupCache.get(new AccountGroup.UUID(uuid));
  }

  private CreateGroupArgs toCreateGroupArgs(GroupInfo groupInfo)
      throws IOException, OrmException, NoSuchAccountException, RestApiException,
          ConfigInvalidException {
    CreateGroupArgs args = new CreateGroupArgs();
    args.setGroupName(groupInfo.name);
    args.groupDescription = groupInfo.description;
    args.visibleToAll = cfg.getBoolean("groups", "newGroupsVisibleToAll", false);
    if (!groupInfo.ownerId.equals(groupInfo.id)) {
      args.ownerGroupId = getGroupByUUID(groupInfo.ownerId).get().getId();
    }
    Set<Account.Id> initialMembers = new HashSet<>();
    for (AccountInfo member : groupInfo.members) {
      initialMembers.add(accountUtil.resolveUser(api, member));
    }
    args.initialMembers = initialMembers;
    return args;
  }

  private AccountGroup createGroup(Input input, GroupInfo info)
      throws OrmException, NoSuchAccountException, IOException, RestApiException,
          ConfigInvalidException {
    String uniqueName = getUniqueGroupName(info.name);
    if (!info.name.equals(uniqueName)) {
      log.warn(
          String.format(
              "Group %s with UUID %s is imported with name %s", info.name, info.id, uniqueName));
      info.name = uniqueName;
    }
    AccountGroup group = createAccountGroup(info);
    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 ResourceConflictException(info.name);
    }
    db.accountGroups().insert(Collections.singleton(group));
    groupCache.evict(group.getGroupUUID(), group.getId(), group.getNameKey());

    if (!info.id.equals(info.ownerId)) {
      if (getGroupByUUID(info.ownerId) == null) {
        if (isInternalGroup(new AccountGroup.UUID(info.ownerId))) {
          String ownerGroupName = getGroupName(info.ownerId);
          if (input.importOwnerGroup) {
            importGroupFactory
                .create(new AccountGroup.NameKey(ownerGroupName))
                .apply(new ConfigResource(), input);
          } else {
            throw new IllegalStateException(
                String.format(
                    "Cannot set non-existing group %s as owner of group %s.",
                    ownerGroupName, info.name));
          }
        }
      }
      group.setOwnerGroupUUID(new AccountGroup.UUID(info.ownerId));
      db.accountGroups().upsert(Collections.singleton(group));
    }

    addMembers(group.getId(), info.members);
    addGroups(input, group.getId(), info.name, info.includes);

    groupCache.evict(group.getGroupUUID(), group.getId(), group.getNameKey());

    return group;
  }

  private String getUniqueGroupName(String name) {
    return getUniqueGroupName(name, false);
  }

  private String getUniqueGroupName(String name, boolean appendIndex) {
    if (getGroupByName(name) == null) {
      return name;
    }
    if (appendIndex) {
      int i = 0;
      while (true) {
        String groupName = String.format("%s-%d", name, ++i);
        if (getGroupByName(groupName) == null) {
          return groupName;
        }
      }
    }
    return getUniqueGroupName(String.format("%s_imported", name), true);
  }

  private AccountGroup createAccountGroup(GroupInfo info) throws OrmException {
    AccountGroup.Id groupId = new AccountGroup.Id(db.nextAccountGroupId());
    AccountGroup.UUID uuid = new AccountGroup.UUID(info.id);
    AccountGroup group =
        new AccountGroup(new AccountGroup.NameKey(info.name), groupId, uuid, TimeUtil.nowTs());
    group.setVisibleToAll(cfg.getBoolean("groups", "newGroupsVisibleToAll", false));
    group.setDescription(info.description);
    return group;
  }

  private void addMembers(AccountGroup.Id groupId, List<AccountInfo> members)
      throws OrmException, NoSuchAccountException, IOException, RestApiException,
          ConfigInvalidException {
    List<AccountGroupMember> memberships = new ArrayList<>();
    for (AccountInfo member : members) {
      Account.Id userId = accountUtil.resolveUser(api, member);
      AccountGroupMember membership =
          new AccountGroupMember(new AccountGroupMember.Key(userId, groupId));
      memberships.add(membership);
    }
    db.accountGroupMembers().insert(memberships);

    for (AccountInfo member : members) {
      accountCache.evict(accountUtil.resolveUser(api, member));
    }
  }

  private void addGroups(
      Input input, AccountGroup.Id groupId, String groupName, List<GroupInfo> includedGroups)
      throws NoSuchAccountException, OrmException, IOException, RestApiException,
          ConfigInvalidException {
    List<AccountGroupById> includeList = new ArrayList<>();
    for (GroupInfo includedGroup : includedGroups) {
      if (isInternalGroup(new AccountGroup.UUID(includedGroup.id))) {
        if (getGroupByUUID(includedGroup.id) == null) {
          String includedGroupName = getGroupName(includedGroup.id);
          if (input.importIncludedGroups) {
            importGroupFactory
                .create(new AccountGroup.NameKey(includedGroupName))
                .apply(new ConfigResource(), input);
          } else {
            throw new IllegalStateException(
                String.format(
                    "Cannot include non-existing group %s into group %s.",
                    includedGroupName, groupName));
          }
        }
      }
      AccountGroup.UUID memberUUID = new AccountGroup.UUID(includedGroup.id);
      AccountGroupById groupInclude =
          new AccountGroupById(new AccountGroupById.Key(groupId, memberUUID));
      includeList.add(groupInclude);
    }
    db.accountGroupById().insert(includeList);

    for (GroupInfo member : includedGroups) {
      groupIncludeCache.evictParentGroupsOf(new AccountGroup.UUID(member.id));
    }
  }

  private String getGroupName(String uuid) throws BadRequestException, IOException, OrmException {
    return api.getGroup(uuid).name;
  }
}
