// Copyright (C) 2011 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 com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.common.data.PermissionRange;
import com.google.gerrit.common.data.PermissionRule;
import com.google.gerrit.common.data.PermissionRule.Action;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.PeerDaemonUser;
import com.google.gerrit.server.git.QueueProvider;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.project.ProjectCache;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/** Access control management for server-wide capabilities. */
public class CapabilityControl {
  public static interface Factory {
    public CapabilityControl create(CurrentUser user);
  }

  private final CapabilityCollection capabilities;
  private final CurrentUser user;
  private final Map<String, List<PermissionRule>> effective;

  private Boolean canAdministrateServer;
  private Boolean canEmailReviewers;

  @Inject
  CapabilityControl(ProjectCache projectCache, @Assisted CurrentUser currentUser) {
    capabilities = projectCache.getAllProjects().getCapabilityCollection();
    user = currentUser;
    effective = new HashMap<>();
  }

  /** Identity of the user the control will compute for. */
  public CurrentUser getCurrentUser() {
    return user;
  }

  /** @return true if the user can administer this server. */
  public boolean canAdministrateServer() {
    if (canAdministrateServer == null) {
      if (user.getRealUser() != user) {
        canAdministrateServer = false;
      } else {
        canAdministrateServer = user instanceof PeerDaemonUser
            || matchAny(capabilities.administrateServer, ALLOWED_RULE);
      }
    }
    return canAdministrateServer;
  }

  /** @return true if the user can create an account for another user. */
  public boolean canCreateAccount() {
    return canPerform(GlobalCapability.CREATE_ACCOUNT)
      || canAdministrateServer();
  }

  /** @return true if the user can create a group. */
  public boolean canCreateGroup() {
    return canPerform(GlobalCapability.CREATE_GROUP)
      || canAdministrateServer();
  }

  /** @return true if the user can create a project. */
  public boolean canCreateProject() {
    return canPerform(GlobalCapability.CREATE_PROJECT)
      || canAdministrateServer();
  }

  /** @return true if the user can email reviewers. */
  public boolean canEmailReviewers() {
    if (canEmailReviewers == null) {
      canEmailReviewers =
          matchAny(capabilities.emailReviewers, ALLOWED_RULE)
          || !matchAny(capabilities.emailReviewers, Predicates.not(ALLOWED_RULE));

    }
    return canEmailReviewers;
  }

  /** @return true if the user can kill any running task. */
  public boolean canKillTask() {
    return canPerform(GlobalCapability.KILL_TASK)
      || canAdministrateServer();
  }

  /** @return true if the user can view all accounts. */
  public boolean canViewAllAccounts() {
    return canPerform(GlobalCapability.VIEW_ALL_ACCOUNTS)
      || canAdministrateServer();
  }

  /** @return true if the user can view the server caches. */
  public boolean canViewCaches() {
    return canPerform(GlobalCapability.VIEW_CACHES)
      || canAdministrateServer();
  }

  /** @return true if the user can flush the server's caches. */
  public boolean canFlushCaches() {
    return canPerform(GlobalCapability.FLUSH_CACHES)
      || canAdministrateServer();
  }

  /** @return true if the user can view open connections. */
  public boolean canViewConnections() {
    return canPerform(GlobalCapability.VIEW_CONNECTIONS)
        || canAdministrateServer();
  }

  /** @return true if the user can view the installed plugins. */
  public boolean canViewPlugins() {
    return canPerform(GlobalCapability.VIEW_PLUGINS)
      || canAdministrateServer();
  }

  /** @return true if the user can view the entire queue. */
  public boolean canViewQueue() {
    return canPerform(GlobalCapability.VIEW_QUEUE)
      || canAdministrateServer();
  }

  /** @return true if the user can access the database (with gsql). */
  public boolean canAccessDatabase() {
    return canPerform(GlobalCapability.ACCESS_DATABASE);
  }

  /** @return true if the user can stream Gerrit events. */
  public boolean canStreamEvents() {
    return canPerform(GlobalCapability.STREAM_EVENTS)
        || canAdministrateServer();
  }

  /** @return true if the user can run the Git garbage collection. */
  public boolean canRunGC() {
    return canPerform(GlobalCapability.RUN_GC)
        || canAdministrateServer();
  }

  /** @return true if the user can generate HTTP passwords for users other than self. */
  public boolean canGenerateHttpPassword() {
    return canPerform(GlobalCapability.GENERATE_HTTP_PASSWORD)
        || canAdministrateServer();
  }

  /** @return true if the user can impersonate another user. */
  public boolean canRunAs() {
    return canPerform(GlobalCapability.RUN_AS);
  }

  /** @return which priority queue the user's tasks should be submitted to. */
  public QueueProvider.QueueType getQueueType() {
    // If a non-generic group (that is not Anonymous Users or Registered Users)
    // grants us INTERACTIVE permission, use the INTERACTIVE queue even if
    // BATCH was otherwise granted. This allows site administrators to grant
    // INTERACTIVE to Registered Users, and BATCH to 'CI Servers' and have
    // the 'CI Servers' actually use the BATCH queue while everyone else gets
    // to use the INTERACTIVE queue without additional grants.
    //
    GroupMembership groups = user.getEffectiveGroups();
    boolean batch = false;
    for (PermissionRule r : capabilities.priority) {
      if (match(groups, r)) {
        switch (r.getAction()) {
          case INTERACTIVE:
            if (!SystemGroupBackend.isAnonymousOrRegistered(r.getGroup())) {
              return QueueProvider.QueueType.INTERACTIVE;
            }
            break;

          case BATCH:
            batch = true;
            break;

          case ALLOW:
          case BLOCK:
          case DENY:
            break;
        }
      }
    }

    if (batch) {
      // If any of our groups matched to the BATCH queue, use it.
      return QueueProvider.QueueType.BATCH;
    } else {
      return QueueProvider.QueueType.INTERACTIVE;
    }
  }

  /** True if the user has this permission. Works only for non labels. */
  public boolean canPerform(String permissionName) {
    if (GlobalCapability.ADMINISTRATE_SERVER.equals(permissionName)) {
      return canAdministrateServer();
    } else {
      return !access(permissionName).isEmpty();
    }
  }

  /** The range of permitted values associated with a label permission. */
  public PermissionRange getRange(String permission) {
    if (GlobalCapability.hasRange(permission)) {
      return toRange(permission, access(permission));
    }
    return null;
  }

  private static PermissionRange toRange(String permissionName,
      List<PermissionRule> ruleList) {
    int min = 0;
    int max = 0;
    if (ruleList.isEmpty()) {
      PermissionRange.WithDefaults defaultRange =
          GlobalCapability.getRange(permissionName);
      if (defaultRange != null) {
        min = defaultRange.getDefaultMin();
        max = defaultRange.getDefaultMax();
      }
    } else {
      for (PermissionRule rule : ruleList) {
        min = Math.min(min, rule.getMin());
        max = Math.max(max, rule.getMax());
      }
    }
    return new PermissionRange(permissionName, min, max);
  }

  /** Rules for the given permission, or the empty list. */
  private List<PermissionRule> access(String permissionName) {
    List<PermissionRule> rules = effective.get(permissionName);
    if (rules != null) {
      return rules;
    }

    rules = capabilities.getPermission(permissionName);

    if (rules.isEmpty()) {
      effective.put(permissionName, rules);
      return rules;
    }

    GroupMembership groups = user.getEffectiveGroups();
    if (rules.size() == 1) {
      if (!match(groups, rules.get(0))) {
        rules = Collections.emptyList();
      }
      effective.put(permissionName, rules);
      return rules;
    }

    List<PermissionRule> mine = new ArrayList<>(rules.size());
    for (PermissionRule rule : rules) {
      if (match(groups, rule)) {
        mine.add(rule);
      }
    }

    if (mine.isEmpty()) {
      mine = Collections.emptyList();
    }
    effective.put(permissionName, mine);
    return mine;
  }

  private static final Predicate<PermissionRule> ALLOWED_RULE = new Predicate<PermissionRule>() {
    @Override
    public boolean apply(PermissionRule rule) {
      return rule.getAction() == Action.ALLOW;
    }
  };

  private boolean matchAny(Iterable<PermissionRule> rules, Predicate<PermissionRule> predicate) {
    Iterable<AccountGroup.UUID> ids = Iterables.transform(
        Iterables.filter(rules, predicate),
        new Function<PermissionRule, AccountGroup.UUID>() {
          @Override
          public AccountGroup.UUID apply(PermissionRule rule) {
            return rule.getGroup().getUUID();
          }
        });
    return user.getEffectiveGroups().containsAnyOf(ids);
  }

  private static boolean match(GroupMembership groups,
      PermissionRule rule) {
    return groups.contains(rule.getGroup().getUUID());
  }
}
