// 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.group;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.common.data.GroupDescription;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AbstractGroupBackend;
import com.google.gerrit.server.account.GroupMembership;
import com.google.gerrit.server.account.ListGroupMembership;
import com.google.gerrit.server.project.ProjectControl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

public class SystemGroupBackend extends AbstractGroupBackend {
  /** Common UUID assigned to the "Anonymous Users" group. */
  public static final AccountGroup.UUID ANONYMOUS_USERS =
      new AccountGroup.UUID("global:Anonymous-Users");

  /** Common UUID assigned to the "Registered Users" group. */
  public static final AccountGroup.UUID REGISTERED_USERS =
      new AccountGroup.UUID("global:Registered-Users");

  /** Common UUID assigned to the "Project Owners" placeholder group. */
  public static final AccountGroup.UUID PROJECT_OWNERS =
      new AccountGroup.UUID("global:Project-Owners");

  /** Common UUID assigned to the "Change Owner" placeholder group. */
  public static final AccountGroup.UUID CHANGE_OWNER =
      new AccountGroup.UUID("global:Change-Owner");

  private static final SortedMap<String, GroupReference> names;
  private static final ImmutableMap<AccountGroup.UUID, GroupReference> uuids;

  static {
    SortedMap<String, GroupReference> n = new TreeMap<>();
    ImmutableMap.Builder<AccountGroup.UUID, GroupReference> u =
        ImmutableMap.builder();
    AccountGroup.UUID[] all = {
        ANONYMOUS_USERS,
        REGISTERED_USERS,
        PROJECT_OWNERS,
        CHANGE_OWNER,
    };
    for (AccountGroup.UUID uuid : all) {
      int c = uuid.get().indexOf(':');
      String name = uuid.get().substring(c + 1).replace('-', ' ');
      GroupReference ref = new GroupReference(uuid, name);
      n.put(ref.getName().toLowerCase(Locale.US), ref);
      u.put(ref.getUUID(), ref);
    }
    names = Collections.unmodifiableSortedMap(n);
    uuids = u.build();
  }

  public static boolean isSystemGroup(AccountGroup.UUID uuid) {
    return uuid.get().startsWith("global:");
  }

  public static boolean isAnonymousOrRegistered(GroupReference ref) {
    return isAnonymousOrRegistered(ref.getUUID());
  }

  public static boolean isAnonymousOrRegistered(AccountGroup.UUID uuid) {
    return ANONYMOUS_USERS.equals(uuid) || REGISTERED_USERS.equals(uuid);
  }

  public static GroupReference getGroup(AccountGroup.UUID uuid) {
    return checkNotNull(uuids.get(uuid), "group %s not found", uuid.get());
  }

  @Override
  public boolean handles(AccountGroup.UUID uuid) {
    return isSystemGroup(uuid);
  }

  @Override
  public GroupDescription.Basic get(AccountGroup.UUID uuid) {
    final GroupReference ref = getGroup(uuid);
    if (ref != null) {
      return new GroupDescription.Basic() {
        @Override
        public String getName() {
          return ref.getName();
        }

        @Override
        public AccountGroup.UUID getGroupUUID() {
          return ref.getUUID();
        }

        @Override
        public String getUrl() {
          return null;
        }

        @Override
        public String getEmailAddress() {
          return null;
        }
      };
    }
    return null;
  }

  @Override
  public Collection<GroupReference> suggest(String name, ProjectControl project) {
    String nameLC = name.toLowerCase(Locale.US);
    SortedMap<String, GroupReference> matches = names.tailMap(nameLC);
    if (matches.isEmpty()) {
      return Collections.emptyList();
    }

    List<GroupReference> r = new ArrayList<>(matches.size());
    for (Map.Entry<String, GroupReference> e : matches.entrySet()) {
      if (e.getKey().startsWith(nameLC)) {
        r.add(e.getValue());
      } else {
        break;
      }
    }
    return r;
  }

  @Override
  public GroupMembership membershipsOf(IdentifiedUser user) {
    return new ListGroupMembership(ImmutableSet.of(
        ANONYMOUS_USERS,
        REGISTERED_USERS));
  }
}

@@ -3834,33 +3834,8 @@
 d);%0A
-    if (ref != null) %7B%0A  
     
@@ -3874,26 +3874,24 @@
 c() %7B%0A      
- 
- 
 @Override%0A  
@@ -3880,34 +3880,32 @@
       @Override%0A
-  
       public Str
@@ -3916,26 +3916,24 @@
 getName() %7B%0A
-  
         retu
@@ -3948,39 +3948,35 @@
 etName();%0A      
-  
 %7D%0A%0A
-  
       @Override%0A
@@ -3967,34 +3967,32 @@
       @Override%0A
-  
       public Acc
@@ -4027,26 +4027,24 @@
 ) %7B%0A        
-  
 return ref.g
@@ -4049,26 +4049,24 @@
 .getUUID();%0A
-  
       %7D%0A%0A   
@@ -4060,34 +4060,32 @@
 %0A      %7D%0A%0A      
-  
 @Override%0A      
@@ -4070,34 +4070,32 @@
       @Override%0A
-  
       public Str
@@ -4105,26 +4105,24 @@
  getUrl() %7B%0A
-  
         retu
@@ -4132,31 +4132,27 @@
 null;%0A      
-  
 %7D%0A%0A
-  
       @Overr
@@ -4157,26 +4157,24 @@
 rride%0A      
- 
- 
 public Strin
@@ -4199,26 +4199,24 @@
 ) %7B%0A        
-  
 return null;
@@ -4226,42 +4226,15 @@
     
-  %7D%0A      %7D;%0A    %7D%0A    return null
+%7D%0A    %7D
 ;%0A  

Remove redundant null check