// 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.base.Strings.nullToEmpty;
import static java.util.Comparator.comparing;

import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.exceptions.NoSuchGroupException;
import com.google.gerrit.extensions.common.GroupInfo;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.account.GroupControl;
import com.google.gerrit.server.group.GroupResource;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.ArrayList;
import java.util.List;

@Singleton
public class ListSubgroups implements RestReadView<GroupResource> {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final GroupControl.Factory controlFactory;
  private final GroupJson json;

  @Inject
  ListSubgroups(GroupControl.Factory controlFactory, GroupJson json) {
    this.controlFactory = controlFactory;
    this.json = json;
  }

  @Override
  public Response<List<GroupInfo>> apply(GroupResource rsrc)
      throws NotInternalGroupException, PermissionBackendException {
    GroupDescription.Internal group =
        rsrc.asInternalGroup().orElseThrow(NotInternalGroupException::new);

    return Response.ok(getDirectSubgroups(group, rsrc.getControl()));
  }

  public List<GroupInfo> getDirectSubgroups(
      GroupDescription.Internal group, GroupControl groupControl)
      throws PermissionBackendException {
    boolean ownerOfParent = groupControl.isOwner();
    List<GroupInfo> included = new ArrayList<>();
    for (AccountGroup.UUID subgroupUuid : group.getSubgroups()) {
      try {
        GroupControl i = controlFactory.controlFor(subgroupUuid);
        if (ownerOfParent || i.isVisible()) {
          included.add(json.format(i.getGroup()));
        }
      } catch (NoSuchGroupException notFound) {
        logger.atWarning().log(
            "Group %s no longer available, subgroup of %s", subgroupUuid, group.getName());
        continue;
      }
    }
    included.sort(
        comparing((GroupInfo g) -> nullToEmpty(g.name)).thenComparing(g -> nullToEmpty(g.id)));
    return included;
  }
}
