package com.atlassian.stash.experimental.user;

import com.atlassian.annotations.ExperimentalApi;
import com.atlassian.bitbucket.permission.Permission;
import com.atlassian.bitbucket.permission.PermissionAdminService;
import com.atlassian.bitbucket.permission.PermittedGroup;
import com.atlassian.bitbucket.permission.PermittedUser;
import com.atlassian.bitbucket.user.ApplicationUser;
import com.atlassian.bitbucket.util.Page;
import com.atlassian.bitbucket.util.PageRequest;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
 * An experimental interface for querying a user, groups permissions.
 *
 * WARNING: this interface is experimental and is subject to change between minor versions of Stash up to and including
 * removal of this interface or parts thereof. It is not for consumption by non-Atlassian plugins and no consideration
 * will be given to nor guarantees made for its compatibility between releases. Basically, don't use it unless
 * you're a Stash developer.
 *
 * @since 2.12
 */
@ExperimentalApi
public interface ExperimentalPermissionAdminService extends PermissionAdminService {
    /**
     * Retrieves a page of {@link ProjectPermission projects} and their highest global permission for the specified user.
     * Only project permissions <i>explicitly</i> granted to the user will be returned.
     *
     * @param request specifying the search parameters
     * @param pageRequest bounds the page of users to be returned
     * @return a page containing zero or more projects and their highest granted permission for the specified user
     * @since 2.12
     */
    @Nonnull
    Page<ProjectPermission> searchProjects(@Nonnull ProjectPermissionSearchRequest request, @Nonnull PageRequest pageRequest);

    /**
     * Retrieves a page of {@link RepositoryPermission repositories} and their highest global permission for the
     * specified user. Only repository permissions <i>explicitly</i> granted to the user will be returned.
     *
     * @param request specifying the search parameters
     * @param pageRequest bounds the page of users to be returned
     * @return a page containing zero or more repositories and their highest granted permission for the specified user
     * @since 2.12
     */
    @Nonnull
    Page<RepositoryPermission> searchRepositories(@Nonnull RepositoryPermissionSearchRequest request, @Nonnull PageRequest pageRequest);

    /**
     * Retrieves a page of users who have been explicitly granted permission on the repository, project or globally
     * as specified in the request object.
     *
     * @param request a request describing the search criteria
     * @param pageRequest bounds the page of users to be returned
     * @return a page of users and their permission (as related to the supplied request).
     * @since 2.12
     */
    @Nonnull
    Page<PermittedUser> searchUsers(@Nonnull PermittedUserSearchRequest request,
                                    @Nonnull PageRequest pageRequest);

    /**
     * Retrieves a page of groups who have been explicitly granted permission on the repository, project or globally
     * as specified in the request object.
     *
     * @param request a request describing the search criteria
     * @param pageRequest bounds the page of groups to be returned
     * @return a page of groups and their permission (as related to the supplied request).
     * @since 2.12
     */
    @Nonnull
    Page<PermittedGroup> searchGroups(@Nonnull PermittedGroupSearchRequest request,
                                      @Nonnull PageRequest pageRequest);

    /**
     * Retrieves a page of users who have not been explicitly granted permission on the repository, project or globally
     * as specified in the request object.
     *
     * @param request a request describing the search criteria
     * @param pageRequest bounds the page of users to be returned
     * @return a page of users
     * @since 2.12
     */
    @Nonnull
    Page<ApplicationUser> searchUsersLacking(@Nonnull PermittedUserSearchRequest request,
                                       @Nonnull PageRequest pageRequest);

    /**
     * Retrieves a page of groups who have not been explicitly granted permission on the repository, project or globally
     * as specified in the request object.
     *
     * @param request a request describing the search criteria
     * @param pageRequest bounds the page of groups to be returned
     * @return a page of group names
     * @since 2.12
     */
    @Nonnull
    Page<String> searchGroupsLacking(@Nonnull PermittedGroupSearchRequest request,
                                     @Nonnull PageRequest pageRequest);

    /**
     * Retrieves the highest directly-granted permission on the specified project for the specified user or null if no
     * permission was granted.
     * @param request specifies the user and project on which permission is being checked
     * @return the highest granted project permission or null if one has not been set
     */
    @Nullable
    Permission getProjectPermission(@Nonnull ProjectPermissionRequest request);

    /**
     * Retrieves the highest directly-granted permission on the specified repository for the specified user or null if no
     * permission has been granted.
     *
     * @param request specifies the user and repository on which permission is being checked
     * @return the highest granted repository permission or null if one has not been set
     */
    @Nullable
    Permission getRepositoryPermission(@Nonnull RepositoryPermissionRequest request);
}
