// Copyright (C) 2009 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.permissions;

import static com.google.gerrit.server.permissions.AbstractLabelPermission.ForUser.ON_BEHALF_OF;
import static com.google.gerrit.server.permissions.DefaultPermissionMappings.labelPermissionName;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Permission;
import com.google.gerrit.entities.PermissionRange;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.conditions.BooleanCondition;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.permissions.PermissionBackend.ForChange;
import com.google.gerrit.server.query.change.ChangeData;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;

/** Access control management for a user accessing a single change. */
class ChangeControl {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final RefControl refControl;
  private final ChangeData changeData;

  ChangeControl(RefControl refControl, ChangeData changeData) {
    this.refControl = refControl;
    this.changeData = changeData;
  }

  ForChange asForChange() {
    return new ForChangeImpl();
  }

  private CurrentUser getUser() {
    return refControl.getUser();
  }

  private ProjectControl getProjectControl() {
    return refControl.getProjectControl();
  }

  private Change getChange() {
    return changeData.change();
  }

  /** Can this user see this change? */
  boolean isVisible() {
    if (getChange().isPrivate() && !isPrivateVisible(changeData)) {
      return false;
    }
    // Does the user have READ permission on the destination?
    return refControl.asForRef().testOrFalse(RefPermission.READ);
  }

  /** Can this user abandon this change? */
  private boolean canAbandon() {
    return isOwner() // owner (aka creator) of the change can abandon
        || refControl.isOwner() // branch owner can abandon
        || getProjectControl().isOwner() // project owner can abandon
        || refControl.canPerform(Permission.ABANDON) // user can abandon a specific ref
        || getProjectControl().isAdmin();
  }

  /** Can this user rebase this change? */
  private boolean canRebase() {
    return (isOwner() || refControl.canSubmit(isOwner()) || refControl.canRebase())
        && refControl.asForRef().testOrFalse(RefPermission.CREATE_CHANGE);
  }

  /**
   * Can this user rebase this change on behalf of the uploader?
   *
   * <p>This only checks the permissions of the rebaser (aka the impersonating user).
   *
   * <p>In addition rebase on behalf of the uploader requires the uploader (aka the impersonated
   * user) to have permissions to create the new patch set. These permissions need to be checked
   * separately.
   */
  private boolean canRebaseOnBehalfOfUploader() {
    return (isOwner() || refControl.canSubmit(isOwner()) || refControl.canRebase());
  }

  /** Can this user restore this change? */
  private boolean canRestore() {
    // Anyone who can abandon the change can restore it, as long as they can create changes.
    return canAbandon() && refControl.asForRef().testOrFalse(RefPermission.CREATE_CHANGE);
  }

  /** Can this user revert this change? */
  private boolean canRevert() {
    return refControl.canRevert() && refControl.asForRef().testOrFalse(RefPermission.CREATE_CHANGE);
  }

  /** The range of permitted values associated with a label permission. */
  private PermissionRange getRange(String permission) {
    return refControl.getRange(permission, isOwner());
  }

  /** Can this user add a patch set to this change? */
  private boolean canAddPatchSet() {
    if (!refControl.asForRef().testOrFalse(RefPermission.CREATE_CHANGE)) {
      return false;
    }
    if (isOwner()) {
      return true;
    }
    return refControl.canAddPatchSet();
  }

  /** Is this user the owner of the change? */
  private boolean isOwner() {
    if (getUser().isIdentifiedUser()) {
      Account.Id id = getUser().asIdentifiedUser().getAccountId();
      return id.equals(getChange().getOwner());
    }
    return false;
  }

  /** Is this user a reviewer for the change? */
  private boolean isReviewer(ChangeData cd) {
    if (getUser().isIdentifiedUser()) {
      Collection<Account.Id> results = cd.reviewers().all();
      return results.contains(getUser().getAccountId());
    }
    return false;
  }

  /** Can this user edit the topic name? */
  private boolean canEditTopicName() {
    if (getChange().isNew()) {
      return isOwner() // owner (aka creator) of the change can edit topic
          || refControl.isOwner() // branch owner can edit topic
          || getProjectControl().isOwner() // project owner can edit topic
          || refControl.canPerform(
              Permission.EDIT_TOPIC_NAME) // user can edit topic on a specific ref
          || getProjectControl().isAdmin();
    }
    return refControl.canForceEditTopicName();
  }

  /** Can this user toggle WorkInProgress state? */
  private boolean canToggleWorkInProgressState() {
    return isOwner()
        || getProjectControl().isOwner()
        || refControl.canPerform(Permission.TOGGLE_WORK_IN_PROGRESS_STATE)
        || getProjectControl().isAdmin();
  }

  /** Can this user edit the description? */
  private boolean canEditDescription() {
    if (getChange().isNew()) {
      return isOwner() // owner (aka creator) of the change can edit desc
          || refControl.isOwner() // branch owner can edit desc
          || getProjectControl().isOwner() // project owner can edit desc
          || getProjectControl().isAdmin();
    }
    return false;
  }

  /** Can this user edit the hashtag name? */
  private boolean canEditHashtags() {
    return isOwner() // owner (aka creator) of the change can edit hashtags
        || refControl.isOwner() // branch owner can edit hashtags
        || getProjectControl().isOwner() // project owner can edit hashtags
        || refControl.canPerform(
            Permission.EDIT_HASHTAGS) // user can edit hashtag on a specific ref
        || getProjectControl().isAdmin();
  }

  /** Can this user edit the custom keyed values? */
  private boolean canEditCustomKeyedValues() {
    return isOwner() // owner (aka creator) of the change can edit custom keyed values
        || getProjectControl().isAdmin();
  }

  private boolean isPrivateVisible(ChangeData cd) {
    if (isOwner()) {
      logger.atFine().log(
          "%s can see private change %s because this user is the change owner",
          getUser().getLoggableName(), cd.getId());
      return true;
    }

    if (isReviewer(cd)) {
      logger.atFine().log(
          "%s can see private change %s because this user is a reviewer",
          getUser().getLoggableName(), cd.getId());
      return true;
    }

    if (refControl.canPerform(Permission.VIEW_PRIVATE_CHANGES)) {
      logger.atFine().log(
          "%s can see private change %s because this user can view private changes",
          getUser().getLoggableName(), cd.getId());
      return true;
    }

    if (getUser().isInternalUser()) {
      logger.atFine().log(
          "%s can see private change %s because this user is an internal user",
          getUser().getLoggableName(), cd.getId());
      return true;
    }

    logger.atFine().log("%s cannot see private change %s", getUser().getLoggableName(), cd.getId());
    return false;
  }

  private class ForChangeImpl extends ForChange {
    private Map<String, PermissionRange> labels;
    private String resourcePath;

    private ForChangeImpl() {}

    @Override
    public String resourcePath() {
      if (resourcePath == null) {
        resourcePath =
            String.format(
                "/projects/%s/+changes/%s",
                getProjectControl().getProjectState().getName(), changeData.getId().get());
      }
      return resourcePath;
    }

    @Override
    public void check(ChangePermissionOrLabel perm)
        throws AuthException, PermissionBackendException {
      if (!can(perm)) {
        throw new AuthException(
            perm.describeForException()
                + " not permitted"
                + perm.hintForException().map(hint -> " (" + hint + ")").orElse(""));
      }
    }

    @Override
    public <T extends ChangePermissionOrLabel> Set<T> test(Collection<T> permSet)
        throws PermissionBackendException {
      Set<T> ok = newSet(permSet);
      for (T perm : permSet) {
        if (can(perm)) {
          ok.add(perm);
        }
      }
      return ok;
    }

    @Override
    public BooleanCondition testCond(ChangePermissionOrLabel perm) {
      return new PermissionBackendCondition.ForChange(this, perm, getUser());
    }

    private boolean can(ChangePermissionOrLabel perm) throws PermissionBackendException {
      if (perm instanceof ChangePermission) {
        return can((ChangePermission) perm);
      } else if (perm instanceof AbstractLabelPermission) {
        return can((AbstractLabelPermission) perm);
      } else if (perm instanceof AbstractLabelPermission.WithValue) {
        return can((AbstractLabelPermission.WithValue) perm);
      }
      throw new PermissionBackendException(perm + " unsupported");
    }

    private boolean can(ChangePermission perm) throws PermissionBackendException {
      try {
        switch (perm) {
          case READ:
            return isVisible();
          case ABANDON:
            return canAbandon();
          case DELETE:
            return getProjectControl().isAdmin() || refControl.canDeleteChanges(isOwner());
          case ADD_PATCH_SET:
            return canAddPatchSet();
          case EDIT_DESCRIPTION:
            return canEditDescription();
          case EDIT_HASHTAGS:
            return canEditHashtags();
          case EDIT_CUSTOM_KEYED_VALUES:
            return canEditCustomKeyedValues();
          case EDIT_TOPIC_NAME:
            return canEditTopicName();
          case REBASE:
            return canRebase();
          case REBASE_ON_BEHALF_OF_UPLOADER:
            return canRebaseOnBehalfOfUploader();
          case RESTORE:
            return canRestore();
          case REVERT:
            return canRevert();
          case SUBMIT:
            return refControl.canSubmit(isOwner());
          case TOGGLE_WORK_IN_PROGRESS_STATE:
            return canToggleWorkInProgressState();

          case REMOVE_REVIEWER:
          case SUBMIT_AS:
            return refControl.canPerform(changePermissionName(perm));
        }
      } catch (StorageException e) {
        throw new PermissionBackendException("unavailable", e);
      }
      throw new PermissionBackendException(perm + " unsupported");
    }

    private boolean can(AbstractLabelPermission perm) {
      return !label(labelPermissionName(perm)).isEmpty();
    }

    private boolean can(AbstractLabelPermission.WithValue perm) {
      PermissionRange r = label(labelPermissionName(perm));
      if (perm.forUser() == ON_BEHALF_OF && r.isEmpty()) {
        return false;
      }
      return r.contains(perm.value());
    }

    private PermissionRange label(String permission) {
      if (labels == null) {
        labels = Maps.newHashMapWithExpectedSize(4);
      }
      PermissionRange r = labels.get(permission);
      if (r == null) {
        r = getRange(permission);
        labels.put(permission, r);
      }
      return r;
    }
  }

  private static <T extends ChangePermissionOrLabel> Set<T> newSet(Collection<T> permSet) {
    if (permSet instanceof EnumSet) {
      @SuppressWarnings({"unchecked", "rawtypes"})
      Set<T> s = ((EnumSet) permSet).clone();
      s.clear();
      return s;
    }
    return Sets.newHashSetWithExpectedSize(permSet.size());
  }

  private static String changePermissionName(ChangePermission changePermission) {
    // Within this class, it's programmer error to call this method on a
    // ChangePermission that isn't associated with a permission name.
    return DefaultPermissionMappings.changePermissionName(changePermission)
        .orElseThrow(() -> new IllegalStateException("no name for " + changePermission));
  }
}
