// Copyright (C) 2013 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.group;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static java.util.stream.Collectors.toList;

import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Streams;
import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.exceptions.NoSuchGroupException;
import com.google.gerrit.extensions.client.ListGroupsOption;
import com.google.gerrit.extensions.client.ListOption;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountResource;
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.account.GroupControl;
import com.google.gerrit.server.group.GroupResolver;
import com.google.gerrit.server.group.InternalGroupDescription;
import com.google.gerrit.server.group.db.Groups;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.restapi.account.GetGroups;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.kohsuke.args4j.Option;

/** List groups visible to the calling user. */
public class ListGroups implements RestReadView<TopLevelResource> {
  private static final Comparator<GroupDescription.Internal> GROUP_COMPARATOR =
      Comparator.comparing(GroupDescription.Basic::getName);

  protected final GroupCache groupCache;

  private final List<ProjectState> projects = new ArrayList<>();
  private final Set<AccountGroup.UUID> groupsToInspect = new HashSet<>();
  private final GroupControl.Factory groupControlFactory;
  private final GroupControl.GenericFactory genericGroupControlFactory;
  private final Provider<IdentifiedUser> identifiedUser;
  private final IdentifiedUser.GenericFactory userFactory;
  private final GetGroups accountGetGroups;
  private final GroupJson json;
  private final GroupBackend groupBackend;
  private final Groups groups;
  private final GroupResolver groupResolver;

  private EnumSet<ListGroupsOption> options = EnumSet.noneOf(ListGroupsOption.class);
  private boolean visibleToAll;
  private Account.Id user;
  private boolean owned;
  private int limit;
  private int start;
  private String matchSubstring;
  private String matchRegex;
  private String suggest;
  private String ownedBy;

  @Option(
      name = "--project",
      aliases = {"-p"},
      usage = "projects for which the groups should be listed")
  public void addProject(ProjectState project) {
    projects.add(project);
  }

  @Option(
      name = "--visible-to-all",
      usage = "to list only groups that are visible to all registered users")
  public void setVisibleToAll(boolean visibleToAll) {
    this.visibleToAll = visibleToAll;
  }

  @Option(
      name = "--user",
      aliases = {"-u"},
      usage = "user for which the groups should be listed")
  public void setUser(Account.Id user) {
    this.user = user;
  }

  @Option(
      name = "--owned",
      usage =
          "to list only groups that are owned by the"
              + " specified user or by the calling user if no user was specifed")
  public void setOwned(boolean owned) {
    this.owned = owned;
  }

  /**
   * Add a group to inspect.
   *
   * @param uuid UUID of the group
   * @deprecated use {@link #addGroup(AccountGroup.UUID)}.
   */
  @Deprecated
  @Option(
      name = "--query",
      aliases = {"-q"},
      usage = "group to inspect (deprecated: use --group/-g instead)")
  void addGroup_Deprecated(AccountGroup.UUID uuid) {
    addGroup(uuid);
  }

  @Option(
      name = "--group",
      aliases = {"-g"},
      usage = "group to inspect")
  public void addGroup(AccountGroup.UUID uuid) {
    groupsToInspect.add(uuid);
  }

  @Option(
      name = "--limit",
      aliases = {"-n"},
      metaVar = "CNT",
      usage = "maximum number of groups to list")
  public void setLimit(int limit) {
    this.limit = limit;
  }

  @Option(
      name = "--start",
      aliases = {"-S"},
      metaVar = "CNT",
      usage = "number of groups to skip")
  public void setStart(int start) {
    this.start = start;
  }

  @Option(
      name = "--match",
      aliases = {"-m"},
      metaVar = "MATCH",
      usage = "match group substring")
  public void setMatchSubstring(String matchSubstring) {
    this.matchSubstring = matchSubstring;
  }

  @Option(
      name = "--regex",
      aliases = {"-r"},
      metaVar = "REGEX",
      usage = "match group regex")
  public void setMatchRegex(String matchRegex) {
    this.matchRegex = matchRegex;
  }

  @Option(
      name = "--suggest",
      aliases = {"-s"},
      usage = "to get a suggestion of groups")
  public void setSuggest(String suggest) {
    this.suggest = suggest;
  }

  @Option(name = "-o", usage = "Output options per group")
  void addOption(ListGroupsOption o) {
    options.add(o);
  }

  @Option(name = "-O", usage = "Output option flags, in hex")
  void setOptionFlagsHex(String hex) {
    options.addAll(ListOption.fromBits(ListGroupsOption.class, Integer.parseInt(hex, 16)));
  }

  @Option(name = "--owned-by", usage = "list groups owned by the given group uuid")
  public void setOwnedBy(String ownedBy) {
    this.ownedBy = ownedBy;
  }

  @Inject
  protected ListGroups(
      final GroupCache groupCache,
      final GroupControl.Factory groupControlFactory,
      final GroupControl.GenericFactory genericGroupControlFactory,
      final Provider<IdentifiedUser> identifiedUser,
      final IdentifiedUser.GenericFactory userFactory,
      final GetGroups accountGetGroups,
      final GroupResolver groupResolver,
      GroupJson json,
      GroupBackend groupBackend,
      Groups groups) {
    this.groupCache = groupCache;
    this.groupControlFactory = groupControlFactory;
    this.genericGroupControlFactory = genericGroupControlFactory;
    this.identifiedUser = identifiedUser;
    this.userFactory = userFactory;
    this.accountGetGroups = accountGetGroups;
    this.json = json;
    this.groupBackend = groupBackend;
    this.groups = groups;
    this.groupResolver = groupResolver;
  }

  public void setOptions(EnumSet<ListGroupsOption> options) {
    this.options = options;
  }

  public Account.Id getUser() {
    return user;
  }

  public List<ProjectState> getProjects() {
    return projects;
  }

  @Override
  public Response<SortedMap<String, GroupInfo>> apply(TopLevelResource resource) throws Exception {
    SortedMap<String, GroupInfo> output = new TreeMap<>();
    for (GroupInfo info : get()) {
      output.put(MoreObjects.firstNonNull(info.name, "Group " + Url.decode(info.id)), info);
      info.name = null;
    }
    return Response.ok(output);
  }

  public List<GroupInfo> get() throws Exception {
    if (!Strings.isNullOrEmpty(suggest)) {
      return suggestGroups();
    }

    if (!Strings.isNullOrEmpty(matchSubstring) && !Strings.isNullOrEmpty(matchRegex)) {
      throw new BadRequestException("Specify one of m/r");
    }

    if (ownedBy != null) {
      return getGroupsOwnedBy(ownedBy);
    }

    if (owned) {
      return getGroupsOwnedBy(user != null ? userFactory.create(user) : identifiedUser.get());
    }

    if (user != null) {
      return accountGetGroups.apply(new AccountResource(userFactory.create(user))).value();
    }

    return getAllGroups();
  }

  private List<GroupInfo> getAllGroups()
      throws IOException, ConfigInvalidException, PermissionBackendException {
    Pattern pattern = getRegexPattern();
    Stream<GroupDescription.Internal> existingGroups =
        getAllExistingGroups()
            .filter(group -> isRelevant(pattern, group))
            .map(this::loadGroup)
            .flatMap(Streams::stream)
            .filter(this::isVisible)
            .sorted(GROUP_COMPARATOR)
            .skip(start);
    if (limit > 0) {
      existingGroups = existingGroups.limit(limit);
    }
    List<GroupDescription.Internal> relevantGroups = existingGroups.collect(toImmutableList());
    List<GroupInfo> groupInfos = Lists.newArrayListWithCapacity(relevantGroups.size());
    for (GroupDescription.Internal group : relevantGroups) {
      groupInfos.add(json.addOptions(options).format(group));
    }
    return groupInfos;
  }

  private Stream<GroupReference> getAllExistingGroups() throws IOException, ConfigInvalidException {
    if (!projects.isEmpty()) {
      return projects.stream()
          .map(ProjectState::getAllGroups)
          .flatMap(Collection::stream)
          .distinct();
    }
    return groups.getAllGroupReferences();
  }

  private List<GroupInfo> suggestGroups() throws BadRequestException, PermissionBackendException {
    if (conflictingSuggestParameters()) {
      throw new BadRequestException(
          "You should only have no more than one --project and -n with --suggest");
    }
    List<GroupReference> groupRefs =
        groupBackend.suggest(suggest, projects.stream().findFirst().orElse(null)).stream()
            .limit(limit <= 0 ? 10 : Math.min(limit, 10))
            .collect(toList());

    List<GroupInfo> groupInfos = Lists.newArrayListWithCapacity(groupRefs.size());
    for (GroupReference ref : groupRefs) {
      GroupDescription.Basic desc = groupBackend.get(ref.getUUID());
      if (desc != null) {
        groupInfos.add(json.addOptions(options).format(desc));
      }
    }
    return groupInfos;
  }

  private boolean conflictingSuggestParameters() {
    if (Strings.isNullOrEmpty(suggest)) {
      return false;
    }
    if (projects.size() > 1) {
      return true;
    }
    if (visibleToAll) {
      return true;
    }
    if (user != null) {
      return true;
    }
    if (owned) {
      return true;
    }
    if (ownedBy != null) {
      return true;
    }
    if (start != 0) {
      return true;
    }
    if (!groupsToInspect.isEmpty()) {
      return true;
    }
    if (!Strings.isNullOrEmpty(matchSubstring)) {
      return true;
    }
    if (!Strings.isNullOrEmpty(matchRegex)) {
      return true;
    }
    return false;
  }

  private List<GroupInfo> filterGroupsOwnedBy(Predicate<GroupDescription.Internal> filter)
      throws IOException, ConfigInvalidException, PermissionBackendException {
    Pattern pattern = getRegexPattern();
    Stream<? extends GroupDescription.Internal> foundGroups =
        groups
            .getAllGroupReferences()
            .filter(group -> isRelevant(pattern, group))
            .map(this::loadGroup)
            .flatMap(Streams::stream)
            .filter(this::isVisible)
            .filter(filter)
            .sorted(GROUP_COMPARATOR)
            .skip(start);
    if (limit > 0) {
      foundGroups = foundGroups.limit(limit);
    }
    List<GroupDescription.Internal> ownedGroups = foundGroups.collect(toImmutableList());
    List<GroupInfo> groupInfos = new ArrayList<>(ownedGroups.size());
    for (GroupDescription.Internal group : ownedGroups) {
      groupInfos.add(json.addOptions(options).format(group));
    }
    return groupInfos;
  }

  private Optional<GroupDescription.Internal> loadGroup(GroupReference groupReference) {
    return groupCache.get(groupReference.getUUID()).map(InternalGroupDescription::new);
  }

  private List<GroupInfo> getGroupsOwnedBy(String id)
      throws RestApiException, IOException, ConfigInvalidException, PermissionBackendException {
    String uuid = groupResolver.parse(id).getGroupUUID().get();
    return filterGroupsOwnedBy(group -> group.getOwnerGroupUUID().get().equals(uuid));
  }

  private List<GroupInfo> getGroupsOwnedBy(IdentifiedUser user)
      throws IOException, ConfigInvalidException, PermissionBackendException {
    return filterGroupsOwnedBy(group -> isOwner(user, group));
  }

  private boolean isOwner(CurrentUser user, GroupDescription.Internal group) {
    try {
      return genericGroupControlFactory.controlFor(user, group.getGroupUUID()).isOwner();
    } catch (NoSuchGroupException e) {
      return false;
    }
  }

  private Pattern getRegexPattern() {
    return Strings.isNullOrEmpty(matchRegex) ? null : Pattern.compile(matchRegex);
  }

  private boolean isRelevant(Pattern pattern, GroupReference group) {
    if (!Strings.isNullOrEmpty(matchSubstring)) {
      if (!group.getName().toLowerCase(Locale.US).contains(matchSubstring.toLowerCase(Locale.US))) {
        return false;
      }
    } else if (pattern != null) {
      if (!pattern.matcher(group.getName()).matches()) {
        return false;
      }
    }
    return groupsToInspect.isEmpty() || groupsToInspect.contains(group.getUUID());
  }

  private boolean isVisible(GroupDescription.Internal group) {
    if (visibleToAll && !group.isVisibleToAll()) {
      return false;
    }
    GroupControl c = groupControlFactory.controlFor(group);
    return c.isVisible();
  }
}
