// Copyright (C) 2012 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 static com.google.gerrit.server.account.GroupBackends.GROUP_REF_NAME_COMPARATOR;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.MultimapBuilder;
import com.google.common.collect.Sets;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.project.ProjectControl;
import com.google.inject.Inject;
import com.google.inject.Singleton;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Universal implementation of the GroupBackend that works with the injected
 * set of GroupBackends.
 */
@Singleton
public class UniversalGroupBackend implements GroupBackend {
  private static final Logger log =
      LoggerFactory.getLogger(UniversalGroupBackend.class);

  private final DynamicSet<GroupBackend> backends;

  @Inject
  UniversalGroupBackend(DynamicSet<GroupBackend> backends) {
    this.backends = backends;
  }

  @Nullable
  private GroupBackend backend(AccountGroup.UUID uuid) {
    if (uuid != null) {
      for (GroupBackend g : backends) {
        if (g.handles(uuid)) {
          return g;
        }
      }
    }
    return null;
  }

  @Override
  public boolean handles(AccountGroup.UUID uuid) {
    return backend(uuid) != null;
  }

  @Override
  public GroupDescription.Basic get(AccountGroup.UUID uuid) {
    if (uuid == null) {
      return null;
    }
    GroupBackend b = backend(uuid);
    if (b == null) {
      log.debug("Unknown GroupBackend for UUID: " + uuid);
      return null;
    }
    return b.get(uuid);
  }

  @Override
  public Collection<GroupReference> suggest(String name, ProjectControl project) {
    Set<GroupReference> groups = Sets.newTreeSet(GROUP_REF_NAME_COMPARATOR);
    for (GroupBackend g : backends) {
      groups.addAll(g.suggest(name, project));
    }
    return groups;
  }

  @Override
  public GroupMembership membershipsOf(IdentifiedUser user) {
    return new UniversalGroupMembership(user);
  }

  private class UniversalGroupMembership implements GroupMembership {
   private final Map<GroupBackend, GroupMembership> memberships;

   private UniversalGroupMembership(IdentifiedUser user) {
     ImmutableMap.Builder<GroupBackend, GroupMembership> builder =
         ImmutableMap.builder();
     for (GroupBackend g : backends) {
       builder.put(g, g.membershipsOf(user));
     }
     this.memberships = builder.build();
   }

   @Nullable
   private GroupMembership membership(AccountGroup.UUID uuid) {
     if (uuid != null) {
       for (Map.Entry<GroupBackend, GroupMembership> m : memberships.entrySet()) {
         if (m.getKey().handles(uuid)) {
           return m.getValue();
         }
       }
     }
     return null;
   }

   @Override
   public boolean contains(AccountGroup.UUID uuid) {
     if (uuid == null) {
       return false;
     }
     GroupMembership m = membership(uuid);
     if (m == null) {
       log.debug("Unknown GroupMembership for UUID: " + uuid);
       return false;
     }
     return m.contains(uuid);
   }

    @Override
    public boolean containsAnyOf(Iterable<AccountGroup.UUID> uuids) {
      ListMultimap<GroupMembership, AccountGroup.UUID> lookups =
          MultimapBuilder.hashKeys().arrayListValues().build();
      for (AccountGroup.UUID uuid : uuids) {
        if (uuid == null) {
          continue;
        }
        GroupMembership m = membership(uuid);
        if (m == null) {
          log.debug("Unknown GroupMembership for UUID: " + uuid);
          continue;
        }
        lookups.put(m, uuid);
      }
      for (Map.Entry<GroupMembership, Collection<AccountGroup.UUID>> entry
          : lookups .asMap().entrySet()) {
        GroupMembership m = entry.getKey();
        Collection<AccountGroup.UUID> ids = entry.getValue();
        if (ids.size() == 1) {
          if (m.contains(Iterables.getOnlyElement(ids))) {
            return true;
          }
        } else if (m.containsAnyOf(ids)) {
          return true;
        }
      }
      return false;
    }

    @Override
    public Set<AccountGroup.UUID> intersection(Iterable<AccountGroup.UUID> uuids) {
      ListMultimap<GroupMembership, AccountGroup.UUID> lookups =
          MultimapBuilder.hashKeys().arrayListValues().build();
      for (AccountGroup.UUID uuid : uuids) {
        if (uuid == null) {
          continue;
        }
        GroupMembership m = membership(uuid);
        if (m == null) {
          log.debug("Unknown GroupMembership for UUID: " + uuid);
          continue;
        }
        lookups.put(m, uuid);
      }
      Set<AccountGroup.UUID> groups = new HashSet<>();
      for (Map.Entry<GroupMembership, Collection<AccountGroup.UUID>> entry
          : lookups.asMap().entrySet()) {
        groups.addAll(entry.getKey().intersection(entry.getValue()));
      }
      return groups;
    }

    @Override
    public Set<AccountGroup.UUID> getKnownGroups() {
      Set<AccountGroup.UUID> groups = new HashSet<>();
      for (GroupMembership m : memberships.values()) {
        groups.addAll(m.getKnownGroups());
      }
      return groups;
    }
  }

  @Override
  public boolean isVisibleToAll(AccountGroup.UUID uuid) {
    for (GroupBackend g : backends) {
      if (g.handles(uuid)) {
        return g.isVisibleToAll(uuid);
      }
    }
    return false;
  }
}
