/*
 * Created by IntelliJ IDEA.
 * User: Mike
 * Date: Jan 30, 2004
 * Time: 2:14:51 PM
 */
package com.atlassian.confluence.rpc.soap;

import com.atlassian.confluence.rpc.soap.beans.*;
import com.atlassian.confluence.rpc.*;

import java.util.Map;

public interface ConfluenceSoapService extends SecureRpc
{
    public static final String VIEW_PERMISSION = "view";
    public static final String MODIFY_PERMISSION = "modify";
    public static final String COMMENT_PERMISSION = "comment";
    public static final String ADMIN_SPACE_PERMISSION = "admin";

    /*
       Note: We explicitly declare a lot of exceptions here despite them being subclasses of RemoteException.
       This is so that the WSDL picks them up and turns them into SOAP faults properly.
     */

    String login(String username, String password) throws AuthenticationFailedException, RemoteException;

    boolean logout(String token) throws RemoteException;

    /* Spaces API */
    RemoteSpaceSummary[] getSpaces(String token) throws InvalidSessionException, RemoteException;

    RemoteSpace addSpace(String token, RemoteSpace space) throws NotPermittedException, InvalidSessionException, AlreadyExistsException, RemoteException;

    RemoteSpace addPersonalSpace(String token, RemoteSpace space, String username) throws NotPermittedException, InvalidSessionException, AlreadyExistsException, RemoteException;

    Boolean removeSpace(String token, String spaceKey) throws NotPermittedException, InvalidSessionException, RemoteException;

    RemoteSpace getSpace(String token, String spaceKey) throws InvalidSessionException, RemoteException;

    boolean convertToPersonalSpace(String tokem, String userName, String spaceKey, String newName, boolean updateLinks) throws RemoteException;
    /* Permissions API */
    String[] getPermissions(String token, String spaceKey) throws InvalidSessionException, RemoteException;

    String[] getPermissionsForUser(String token, String spaceKey, String userName) throws InvalidSessionException, NotPermittedException, RemoteException;

    // TODO add global permissions
    // TODO add anonymous support
    // TODO remove method overloading

    /**
     * Add a Space Permission for a user or group
     *
     * @param token            the authentication token
     * @param permission       the Space Permission to add
     * @param remoteEntityName the name of the user or group
     * @param spaceKey         the key of the Space affected by this action
     * @return True if successful, false otherwise
     * @throws RemoteException       if the Space Permission is null
     * @throws RemoteException       if the Space does not exist
     * @throws NotPermittedException if the user lacks permissions to perform the action
     * @throws RemoteException       if the remoteEntityName is null or does not match a user or group
     */
    boolean addPermissionToSpace(String token, String permission, String remoteEntityName, String spaceKey) throws RemoteException;

    /**
     * Add Space Permissions for a user or group
     *
     * @param token            the authentication token
     * @param permissions      the Space Permissions to add
     * @param remoteEntityName the name of the user or group
     * @param spaceKey         the key of the Space affected by this action
     * @return True if successful, false otherwise
     * @throws RemoteException       if the Space Permissions array is null
     * @throws RemoteException       if the Space does not exist
     * @throws NotPermittedException if the user lacks permissions to perform the action
     * @throws RemoteException       if the remoteEntityName is null or does not match a user or group
     * @since 2.0
     */
    boolean addPermissionsToSpace(String token, String[] permissions, String remoteEntityName, String spaceKey) throws RemoteException;

    /**
     * Removes a Space Permission for a user or group
     *
     * @param token            the authentication token
     * @param permission       the Space Permission to remove
     * @param remoteEntityName the name of the user or group
     * @param spaceKey         the key of the Space affected by this action
     * @return True if successful, false otherwise
     * @throws RemoteException       if the Space does not exist
     * @throws NotPermittedException if the user lacks permissions to perform the action
     * @throws RemoteException       if the remoteEntityName is null or does not match a user or group
     */
    boolean removePermissionFromSpace(String token, String permission, String remoteEntityName, String spaceKey) throws NotPermittedException, RemoteException;

    /**
     * Add a Space Permission for anonymous users
     *
     * @param token      the authentication token
     * @param permission the Space Permission to add
     * @param spaceKey   the key of the Space affected by this action
     * @return True if successful, false otherwise
     * @throws RemoteException       if the Space Permission is null
     * @throws RemoteException       if the Space does not exist
     * @throws NotPermittedException if the user lacks permissions to perform the action
     * @throws RemoteException       if the remoteEntityName is null or does not match a user or group
     * @since 2.0
     */
    boolean addAnonymousPermissionToSpace(String token, String permission, String spaceKey) throws RemoteException;

    /**
     * Add Space Permissions for anonymous users
     *
     * @param token       the authentication token
     * @param permissions the Space Permissions to add
     * @param spaceKey    the key of the Space affected by this action
     * @return True if successful, false otherwise
     * @throws RemoteException       if the Space Permissions array is null
     * @throws RemoteException       if the Space does not exist
     * @throws NotPermittedException if the user lacks permissions to perform the action
     * @throws RemoteException       if the remoteEntityName is null or does not match a user or group
     * @since 2.0
     */
    boolean addAnonymousPermissionsToSpace(String token, String[] permissions, String spaceKey) throws RemoteException;

    /**
     * Removes a Space Permission for anonymous users
     *
     * @param token      the authentication token
     * @param permission the Space Permission to remove
     * @param spaceKey   the key of the Space affected by this action
     * @return True if successful, false otherwise
     * @throws RemoteException       if the Space does not exist
     * @throws NotPermittedException if the user lacks permissions to perform the action
     * @throws RemoteException       if the remoteEntityName is null or does not match a user or group
     * @since 2.0
     */
    boolean removeAnonymousPermissionFromSpace(String token, String permission, String spaceKey) throws NotPermittedException, RemoteException;

    RemotePermission[] getPagePermissions(String token, long pageId) throws InvalidSessionException, RemoteException;

    String[] getSpaceLevelPermissions(String token) throws RemoteException;

    /* Pages API */
    RemotePageSummary[] getPages(String token, String spaceKey) throws InvalidSessionException, RemoteException;

    RemotePage getPage(String token, String spaceKey, String pageTitle) throws InvalidSessionException, RemoteException;

    RemotePage getPage(String token, long pageId) throws InvalidSessionException, RemoteException;

    RemotePage storePage(String token, RemotePage page) throws VersionMismatchException, NotPermittedException, InvalidSessionException, RemoteException;

    Boolean removePage(String token, long pageId) throws NotPermittedException, InvalidSessionException, RemoteException;

    RemotePageSummary[] getAncestors(String token, long pageId) throws InvalidSessionException, RemoteException;

    RemotePageSummary[] getChildren(String token, long pageId) throws InvalidSessionException, RemoteException;

    RemotePageSummary[] getDescendents(String token, long pageId) throws InvalidSessionException, RemoteException;

    RemoteAttachment[] getAttachments(String token, long pageId) throws InvalidSessionException, RemoteException;

    RemotePageHistory[] getPageHistory(String token, long pageId) throws InvalidSessionException, RemoteException;

    String renderContent(String token, String spaceKey, long pageId, String newContent) throws InvalidSessionException, RemoteException;

    String renderContent(String token, String spaceKey, long pageId, String newContent, Map renderParameters) throws RemoteException;

    /* Attachments API */

    /**
     * Add a new attachment to a ContentEntityObject.
     *
     * @param token          the authentication token
     * @param contentId      the id of the ContentEntityObject to receive the new attachment.
     * @param attachment     RemoteAttachment object containing attachment information
     * @param attachmentData a byte[] continaing the contents of the attachment.
     * @return the newly created attachment
     * @throws RemoteException
     * @since 2.0
     */
    RemoteAttachment addAttachment(String token, long contentId, RemoteAttachment attachment, byte[] attachmentData) throws RemoteException;

    /**
     * @deprecated available for backward compatibility.
     */
    RemoteAttachment addAttachment(String token, RemoteAttachment attachment, byte[] attachmentData) throws RemoteException;

    /**
     * Retrieve information about an attachment.
     *
     * @param token     the authentication token.
     * @param contentId the id of the ContentEntityObject the attachemt belongs to.
     * @param fileName  the name of the attachment.
     * @param version   the version number of the attachment.
     * @return the attachment
     * @throws RemoteException
     * @since 2.0
     */
    RemoteAttachment getAttachment(String token, long contentId, String fileName, int version) throws RemoteException;

    /**
     * Retrieve the contents of an attachment.
     *
     * @param token     the authentication token.
     * @param contentId the id of the ContentEntityObject the attachemt belongs to.
     * @param fileName  the name of the attachment.
     * @param version   the version number of the attachment.
     * @return the attachment's data
     * @throws RemoteException
     * @since 2.0
     */
    byte[] getAttachmentData(String token, long contentId, String fileName, int version) throws RemoteException;

    /**
     * Remove an attachment.
     *
     * @param token     the authentication token.
     * @param contentId the id of the ContentEntityObject the attachment belongs to.
     * @param fileName  the name of the attachment.
     * @return true if the attachment was deleted.
     * @throws RemoteException
     * @since 2.0
     */
    boolean removeAttachment(String token, long contentId, String fileName) throws RemoteException;

    /**
     * Move or rename an attachment
     *
     * @param token             the authentication token.
     * @param originalContentId the id of the ContentEntityObject the attachment belongs to.
     * @param originalFileName  the name of the attachment.
     * @param newContentId      the id of the ContentEntityObject the attachment is to be moved to.
     * @param newFileName       the name the attachment is to be renamed to.
     * @return true
     * @since 2.0
     */
    boolean moveAttachment(String token, long originalContentId, String originalFileName, long newContentId, String newFileName) throws RemoteException;

    /* Comments API */

    /**
     * Retrieves the comments for a given abstract page
     *
     * @param token  the authentication token
     * @param pageId the content ID of the abstract page
     * @return RemoteComment object with the comment details
     * @throws InvalidSessionException
     * @throws RemoteException         if the object for the pageId is null, or the user lacks permissions
     */
    RemoteComment[] getComments(String token, long pageId) throws InvalidSessionException, RemoteException;

    /**
     * Retrieves a comment with the given ID
     *
     * @param token     The token identifying the current user
     * @param commentId The ID of the comment to be retrieved
     * @return A RemoteComment object containing the comment information
     * @throws InvalidSessionException
     * @throws RemoteException         if the comment cannot be found
     * @throws RemoteException         if the comment cannot be viewed by the user
     * @throws RemoteException         if the page the comment is on cannot be viewed by the user
     * @throws RemoteException         if the retrieved object is not a comment
     * @since 2.0
     */
    RemoteComment getComment(String token, long commentId) throws InvalidSessionException, RemoteException;

    /**
     * Adds a comment to a page or blog post
     *
     * @param token   The token identifying the current user
     * @param comment The RemoteComment object containing the comment information
     * @return RemoteComment object
     * @throws InvalidSessionException
     * @throws RemoteException         if the user does not have permission to view the page the comment is being posted to, or it does not exist
     * @throws NotPermittedException   if the user is unable to post the comment
     * @since 2.0
     */
    RemoteComment addComment(String token, RemoteComment comment) throws InvalidSessionException, NotPermittedException, RemoteException;

    /**
     * Removes a comment with the given ID
     *
     * @param token     The token identifying the current user
     * @param commentId The ID of the comment to remove
     * @return True if successful, false otherwise
     * @throws InvalidSessionException
     * @throws RemoteException         if the user does not have permission to view the page the comment is on, or it does not exist
     * @throws RemoteException         if the comment does not exist
     * @throws NotPermittedException   if the user does not have permission to remove the comment
     * @since 2.0
     */
    boolean removeComment(String token, long commentId) throws InvalidSessionException, NotPermittedException, RemoteException;

    /* Search API */
    RemoteSearchResult[] search(String token, String query, int maxResults) throws InvalidSessionException, RemoteException;

    RemoteSearchResult[] search(String token, String query, Map params, int maxResults) throws RemoteException;

    /* Blogpost API */

    /**
     * Retrieves a blog post in the Space with the given spaceKey, with the title 'postTitle' and posted on the day 'dayOfMonth'
     *
     * @param token      the authentication token
     * @param spaceKey   the key of the Space the blog post belongs to
     * @param dayOfMonth the day of the month the blog post was made
     * @param postTitle  the title of the blog post
     * @return A RemoteBlogEntry object
     * @throws RemoteException if the user does not have permission to view the blog post, or it does not exist
     * @since 2.0
     */
    RemoteBlogEntry getBlogEntryByDayAndTitle(String token, String spaceKey, int dayOfMonth, String postTitle) throws RemoteException;

    RemoteBlogEntry getBlogEntry(String token, long entryId) throws RemoteException;

    RemoteBlogEntrySummary[] getBlogEntries(String token, String spaceKey) throws InvalidSessionException, RemoteException;

    RemoteBlogEntry storeBlogEntry(String token, RemoteBlogEntry blogEntry) throws VersionMismatchException, NotPermittedException, InvalidSessionException, RemoteException;

    /* Admin API */
    RemoteServerInfo getServerInfo(String token) throws InvalidSessionException, RemoteException;

    String exportSpace(String token, String spaceKey, String exportType) throws RemoteException;

    String exportSite(String token, boolean exportAttachments) throws RemoteException;

    boolean flushIndexQueue(String token) throws RemoteException;

    boolean clearIndexQueue(String token) throws RemoteException;

    /* Users Remote API */
    // Groups

    /**
     * Retrieves a list of user groups
     *
     * @param token The token identifying the current user
     * @return An array of group names
     * @throws NotPermittedException if the current user lacks permission to administrate
     */
    String[] getGroups(String token) throws NotPermittedException, RemoteException;

    /**
     * Determines whether a group exists
     *
     * @param token     the token identifying the current user
     * @param groupname the group to look up
     * @return True if the user exists, false otherwise
     * @throws InvalidSessionException
     * @throws RemoteException
     * @since 2.0
     */
    boolean hasGroup(String token, String groupname) throws InvalidSessionException, RemoteException;

    /**
     * Adds a new group
     *
     * @param token     The token identifying the current user
     * @param groupname The name of the group to be added
     * @return True when the group was successfully added, false if it already exists
     * @throws NotPermittedException   if the current user lacks permission to administrate
     * @throws InvalidSessionException
     * @throws RemoteException
     */
    boolean addGroup(String token, String groupname) throws NotPermittedException, InvalidSessionException, RemoteException;

    /**
     * Removes an existing group
     * <p/>
     * If a valid defaultGroupName is specified, users will be added to the new group (defaultGroupName).
     *
     * @param token            The token identifying the current user
     * @param groupname        The name of the group to be removed
     * @param defaultGroupName The name of the group that users will be moved to
     * @return True if successful, false otherwise.
     * @throws NotPermittedException   if the current user lacks permission to administrate
     * @throws InvalidSessionException
     * @throws RemoteException         if the given groupname does not exist
     * @throws RemoteException         if the given defaultGroupName does not exist
     */
    boolean removeGroup(String token, String groupname, String defaultGroupName) throws NotPermittedException, InvalidSessionException, RemoteException;

    /**
     * Deletes all global and space permissions for the given group
     *
     * @param token     The token identifying the current user
     * @param groupname The group to delete permissions for
     * @return True if successful, false otherwise.
     * @throws NotPermittedException if the current user lacks permission to administrate
     * @throws RemoteException       if the given groupname does not exist
     */
    boolean removeAllPermissionsForGroup(String token, String groupname) throws RemoteException;

    /**
     * Retrieves the groups that a given user belongs to
     *
     * @param token    The token identifying the current user
     * @param username The username to retrieve groups for
     * @return An array of group names as Strings
     * @throws NotPermittedException   if the current user lacks permission to administrate
     * @throws InvalidSessionException
     * @throws RemoteException         if the given username does not exist
     */
    String[] getUserGroups(String token, String username) throws NotPermittedException, InvalidSessionException, RemoteException;

    /**
     * @param token
     * @param username
     * @param groupname
     * @return True if successful, false otherwise
     * @throws NotPermittedException   if the current user lacks permission to administrate
     * @throws InvalidSessionException
     * @throws RemoteException         if the given username does not exist
     * @throws RemoteException         if the given groupname does not exist
     */
    boolean addUserToGroup(String token, String username, String groupname) throws NotPermittedException, InvalidSessionException, RemoteException;

    /**
     * Removes the given user from a group
     *
     * @param token     The token identifying the current user
     * @param username  The username to remove from a group
     * @param groupname The name of the group the user is to be removed from
     * @return True if successful, false otherwise
     * @throws NotPermittedException   if the current user lacks permission to administrate
     * @throws InvalidSessionException
     * @throws RemoteException         if the given username does not exist
     * @throws RemoteException         if the given groupname does not exist
     */
    boolean removeUserFromGroup(String token, String username, String groupname) throws NotPermittedException, InvalidSessionException, RemoteException;

    // Users

    /**
     * Retrieves a user with the given username
     *
     * @param token    The token identifying the current user
     * @param username The username of the user to be retrieved
     * @return A RemoteUser object, containing the username, full name, email and URL
     * @throws InvalidSessionException
     * @throws RemoteException         if a user with the given username cannot be found
     */
    RemoteUser getUser(String token, String username) throws InvalidSessionException, RemoteException;

    /**
     * Determines whether a user exists
     *
     * @param token    the token identifying the current user
     * @param username the username to look up
     * @return True if the user exists, false otherwise
     * @throws InvalidSessionException
     * @throws RemoteException
     * @since 2.0
     */
    boolean hasUser(String token, String username) throws InvalidSessionException, RemoteException;

    /**
     * Adds a user with the given RemoteUser object and password
     *
     * @param token      The token identifying the current user
     * @param remoteUser The object containing the user information
     * @param password   The password of the user
     * @throws NotPermittedException   if the current user lacks permissions to create new users
     * @throws InvalidSessionException
     * @throws RemoteException         if a user with the given username cannot be found
     */
    void addUser(String token, RemoteUser remoteUser, String password) throws NotPermittedException, InvalidSessionException, RemoteException;

    /**
     * Removes a user with the given username
     *
     * @param token    The token identifying the current user
     * @param username The username of the user to be removed
     * @return True if successful, false otherwise
     * @throws InvalidSessionException
     * @throws NotPermittedException   if the current user lacks the permission to remove users
     * @throws RemoteException         if the given username cannot be found
     * @throws RemoteException         if the user has authored content
     */
    boolean removeUser(String token, String username) throws NotPermittedException, InvalidSessionException, RemoteException;

    /**
     * Edits a user with the values in the given RemoteUser object
     * <p/>
     * Currently this will only update the user's full name and email
     *
     * @param token      The token identifying the current user
     * @param remoteUser The object containing the user information
     * @throws NotPermittedException   if the current user cannot administer users or is not the actual user
     * @throws InvalidSessionException
     * @throws RemoteException         if a user with the given username cannot be found
     * @since 2.0
     */
    boolean editUser(String token, RemoteUser remoteUser) throws NotPermittedException, InvalidSessionException, RemoteException;

    /**
     * Deactivates the given user
     *
     * @param token    The token identifying the current user
     * @param username The username of the user to deactivate
     * @return True if the user was successfully deactivated, false otherwise
     * @throws NotPermittedException   if the current user does not have permissions to perform the action
     * @throws InvalidSessionException
     * @throws RemoteException         if the given username cannot be found
     * @throws RemoteException         if the user has already been deactivated
     * @since 2.0
     */
    boolean deactivateUser(String token, String username) throws NotPermittedException, InvalidSessionException, RemoteException;

    /**
     * Reactivates the given user
     *
     * @param token    The token identifying the current user
     * @param username The username of the user to reactivate
     * @return True if the user was successfully reactivated, false otherwise
     * @throws NotPermittedException   if the current user does not have permissions to perform the action
     * @throws InvalidSessionException
     * @throws RemoteException         if the given username cannot be found
     * @throws RemoteException         if the user is already active
     * @since 2.0
     */
    boolean reactivateUser(String token, String username) throws NotPermittedException, InvalidSessionException, RemoteException;

    /**
     * Returns a list of the current system users
     *
     * @param token   The token identifying the current user
     * @param viewAll Whether all users should be shown. When it is false, all users in the confluence-users group will be returned.
     *                Otherwise, every registered user is returned.
     * @return An array of usernames as Strings
     * @throws NotPermittedException   if the current user does not have administration permissions
     * @throws InvalidSessionException
     * @throws RemoteException
     * @since 2.0
     */
    String[] getActiveUsers(String token, boolean viewAll) throws InvalidSessionException, RemoteException;

    /**
     * Updates a user's information
     * <p/>
     * Currently this will only update a user's "description", stored in the 'content' attribute
     *
     * @param token    The token identifying the current user
     * @param userInfo A RemoteUser object, containing the username, email, fullname, url and information
     * @throws NotPermittedException   if the current user cannot administer users or is not the actual user
     * @throws InvalidSessionException
     * @throws RemoteException         if there was an error saving the personal information
     * @since 2.0
     */
    boolean setUserInformation(String token, RemoteUserInformation userInfo) throws NotPermittedException, InvalidSessionException, RemoteException;

    /**
     * Retrieves a user's information
     *
     * @param token    The token identifying the current user
     * @param username The name of the user to get information on
     * @throws InvalidSessionException
     * @throws RemoteException         if a user with the given username cannot be found
     * @since 2.0
     */
    RemoteUserInformation getUserInformation(String token, String username) throws InvalidSessionException, RemoteException;

    /**
     * Change the current user's password
     *
     * @param token   The token identifying the current user
     * @param oldPass The old password of the user, required for security purposes
     * @param newPass The new password for the user
     * @throws NotPermittedException   if newPass was incorrect
     * @throws InvalidSessionException
     * @throws RemoteException         if oldPass does not match the user's password
     * @throws RemoteException         if newPass is null or an empty String
     * @throws RemoteException         if there are problems setting the password in the UserAccessor
     * @since 2.0
     */
    boolean changeMyPassword(String token, String oldPass, String newPass) throws InvalidSessionException, RemoteException;

    /**
     * Change a user's password
     *
     * @param token    The token identifying the current user
     * @param username The username of the user we are changing the password for
     * @param newPass  The new password for the user
     * @throws NotPermittedException   if the current user does not have permission to administrate the user
     * @throws InvalidSessionException
     * @throws RemoteException         if the user cannot be found
     * @throws RemoteException         if newPass is null or an empty String
     * @throws RemoteException         if there are problems setting the password in the UserAccessor
     * @since 2.0
     */
    boolean changeUserPassword(String token, String username, String newPass) throws NotPermittedException, InvalidSessionException, RemoteException;

    /**
     * Add a profile picture to a user's profile
     *
     * @param userName The user name of the profile
     * @param fileName File name of the picture
     * @param mimeType Image mime type (must be from image/*)
     * @param pictureData The image data
     * @return true if successful
     * @throws NotPermittedException Principal is not permitted to add pictures to the specified profile
     * @throws InvalidSessionException
     * @throws RemoteException if the user can not be found
     * @throws RemoteException if the mimeType is not from image/*
     * @throws RemoteException if the image can not be processed
     * @since 2.2
     */
    boolean addProfilePicture(String token, String userName, String fileName, String mimeType, byte[] pictureData) throws NotPermittedException, InvalidSessionException, RemoteException;

    /* Labels Remote API */

    /**
     * Returns all labels for the given ContentEntityObject ID.
     *
     * @param token    The token identifying the current user
     * @param objectId The ID of the ContentEntityObject the method will retrieve the labels for
     * @return An array of RemoteLabel objects
     * @throws RemoteException if the object cannot be retrieved from the ContentEntityManager
     * @throws RemoteException if the given user does not have VIEW permissions for the object
     * @since 2.0
     */
    RemoteLabel[] getLabelsById(String token, long objectId) throws InvalidSessionException, RemoteException;

    /**
     * Returns the most popular labels for the Confluence instance, with a specified maximum number
     * of results.
     *
     * @param token    The token identifying the current user
     * @param maxCount The maximum number of labels to return. A maxCount of 0 means there is no limit.
     * @return An array of RemoteLabel objects, sorted by descending popularity
     * @since 2.0
     */
    RemoteLabel[] getMostPopularLabels(String token, int maxCount) throws InvalidSessionException, RemoteException;

    /**
     * Returns the most popular labels for the given spaceKey, with a specified maximum number
     * of results.
     *
     * @param token    The token identifying the current user
     * @param spaceKey The key of the space to limit the labels to
     * @param maxCount The maximum number of labels to return. A maxCount of 0 means there is no limit.
     * @return An array of RemoteLabel objects, sorted by descending popularity
     * @throws RemoteException       if the space cannot be retrieved from the SpaceManager
     * @throws NotPermittedException if the given user does not have VIEW permissions for the space
     * @since 2.0
     */
    RemoteLabel[] getMostPopularLabelsInSpace(String token, String spaceKey, int maxCount) throws InvalidSessionException, RemoteException;

    /**
     * Returns the recently used labels for the Confluence instance, with a specified maximum number
     * of results.
     *
     * @param token      The token identifying the current user
     * @param maxResults The maximum number of labels to return. A value of 0 means the default is used.
     * @return An array of RemoteLabel objects, sorted by most recent use
     * @since 2.0
     */
    RemoteLabel[] getRecentlyUsedLabels(String token, int maxResults) throws InvalidSessionException, RemoteException;

    /**
     * Returns the recently used labels for the given spaceKey, with a specified maximum number
     * of results.
     *
     * @param token      The token identifying the current user
     * @param spaceKey   The key of the space to limit the labels to
     * @param maxResults The maximum number of labels to return. A value of 0 means the default is used.
     * @return An array of RemoteLabel objects, sorted by most recent use
     * @throws RemoteException       if the space does not exist, or the user lacks permission to view it
     * @throws NotPermittedException if the given user does not have VIEW permissions for the space
     * @since 2.0
     */
    RemoteLabel[] getRecentlyUsedLabelsInSpace(String token, String spaceKey, int maxResults) throws InvalidSessionException, RemoteException;

    /**
     * Returns an array of Spaces that have been labelled with labelName
     *
     * @param token     The token identifying the current user
     * @param labelName The name of the label (namespace prefixes permitted)
     * @return An array of RemoteSpace instances
     * @throws InvalidSessionException
     * @throws RemoteException         if labelName is an empty string or null
     * @throws RemoteException         if labelName contains an invalid namespace prefix
     * @throws RemoteException         if a label named labelName cannot be found
     * @since 2.0
     */
    RemoteSpace[] getSpacesWithLabel(String token, String labelName) throws InvalidSessionException, RemoteException;

    /**
     * Returns the labels related to the given label name, with a specified maximum number
     * of results.
     *
     * @param token      The token identifying the current user
     * @param labelName  The name of the label (namespace prefixes permitted)
     * @param maxResults The maximum number of labels to return. A value of 0 means the default is used.
     * @return An array of RemoteLabel objects (sorted by frequency of use)
     * @throws RemoteException if labelName is an empty string or null
     * @throws RemoteException if labelName contains an invalid namespace prefix
     * @throws RemoteException if a label named labelName cannot be found
     * @since 2.0
     */
    RemoteLabel[] getRelatedLabels(String token, String labelName, int maxResults) throws InvalidSessionException, RemoteException;

    /**
     * Returns the labels related to the given label name for the given spaceKey, with a specified maximum number
     * of results.
     *
     * @param token      The token identifying the current user
     * @param labelName  The name of the label (namespace prefixes permitted)
     * @param spaceKey   The key of the space to limit the labels to
     * @param maxResults The maximum number of labels to return. A maxCount of 0 means the default is used.
     * @return An array of RemoteLabel objects (sorted by frequency of use)
     * @throws RemoteException if labelName is an empty string or null
     * @throws RemoteException if labelName contains an invalid namespace prefix
     * @throws RemoteException if a label named labelName cannot be found
     * @throws RemoteException if the Space does not exist, or the user does not have VIEW permissions
     * @since 2.0
     */
    RemoteLabel[] getRelatedLabelsInSpace(String token, String labelName, String spaceKey, int maxResults) throws InvalidSessionException, RemoteException;

    /**
     * Retrieves the labels matching the given labelName, namespace or owner.
     * <p/>
     * This method can be used to retrieve labels of a specfic type, such as personal labels, by setting the namespace.
     * <p/>
     * Parameters with empty strings are ignored.
     *
     * @param token     the authentication token for the user
     * @param labelName the name of the label to search for (not parsed for prefixes)
     * @param namespace the namespace to restrict by
     * @param spaceKey  the key of the space to restrict by
     * @param owner     the owner of the labels
     * @return an array of matching RemoteLabel objects
     * @throws InvalidSessionException
     * @throws RemoteException         if labelName is an empty string or null
     * @throws RemoteException         if labelName contains an invalid namespace prefix
     * @throws RemoteException         if a label named labelName cannot be found
     * @throws RemoteException         if the Space does not exist, or the user does not have VIEW permissions
     * @throws RemoteException         if the owner is not a valid user
     * @see com.atlassian.confluence.labels.Namespace
     * @since 2.0
     */
    RemoteLabel[] getLabelsByDetail(String token, String labelName, String namespace, String spaceKey, String owner) throws InvalidSessionException, RemoteException;

    /**
     * Returns the content for a given label ID
     *
     * @param token   The token identifying the current user
     * @param labelId The ID of the label
     * @return An array of RemoteSearchResult objects
     * @throws RemoteException if a Label could not be retrieved for the given ID
     * @since 2.0
     */
    RemoteSearchResult[] getLabelContentById(String token, long labelId) throws InvalidSessionException, RemoteException;

    /**
     * Returns the content for a given label name
     *
     * @param token     The token identifying the current user
     * @param labelName The name of a label (namespace prefixes permitted)
     * @return An array of RemoteSearchResult objects
     * @throws RemoteException if the label name is null
     * @throws RemoteException if the label name is an empty String
     * @throws RemoteException if a Label could not be retrieved for the given ID
     * @since 2.0
     */
    RemoteSearchResult[] getLabelContentByName(String token, String labelName) throws InvalidSessionException, RemoteException;

    /**
     * Returns the content for a given label object
     *
     * @param token       The token identifying the current user
     * @param labelObject The RemoteLabel object
     * @return An array of RemoteSearchResult objects
     * @throws RemoteException if the RemoteLabel object is null
     * @throws RemoteException if a Label could not be retrieved for the given ID
     * @since 2.0
     */
    RemoteSearchResult[] getLabelContentByObject(String token, RemoteLabel labelObject) throws InvalidSessionException, RemoteException;

    /**
     * Returns all Spaces that have content labelled with labelName
     *
     * @param token     The token identifying the current user
     * @param labelName The label to retrieve the content for (namespace prefixes permitted)
     * @return An array of RemoteSpace instances (order undefined)
     * @throws InvalidSessionException
     * @throws RemoteException         if labelName is an empty string or null
     * @throws RemoteException         if labelName contains an invalid namespace prefix
     * @throws RemoteException         if a label named labelName cannot be found
     * @since 2.0
     */
    RemoteSpace[] getSpacesContainingContentWithLabel(String token, String labelName) throws InvalidSessionException, RemoteException;

    /**
     * Adds a label to the object with the given ContentEntityObject ID.
     *
     * @param token     The token identifying the current user
     * @param labelName The name of the label(s) to be added to the ContentEntityObject, in the form of a space-separated string
     * @param objectId  The ID of the ContentEntityObject the method will act on
     * @return True if successfully added, false otherwise.
     * @throws RemoteException       if the label name is null or an empty String
     * @throws RemoteException       if the split label name is invalid (as determined by LabelUtil.split())
     * @throws RemoteException       if the object was not valid
     * @throws RemoteException       if the user does not have VIEW permissions for the object
     * @throws RemoteException       if the label could not be created
     * @throws NotPermittedException if the user lacks EDIT permissions for the object
     * @since 2.0
     */
    boolean addLabelByName(String token, String labelName, long objectId) throws NotPermittedException, InvalidSessionException, RemoteException;

    /**
     * Adds a label with the given ID to the object with the given ContentEntityObject ID.
     *
     * @param token    The token identifying the current user
     * @param labelId  The ID of the label to be added to the ContentEntityObject
     * @param objectId The ID of the ContentEntityObject the method will act on
     * @return True if successfully added, false otherwise.
     * @throws RemoteException       if a Label could not be retrieved for the given ID
     * @throws RemoteException       if the object was not valid
     * @throws RemoteException       if the user lacks VIEW permissions for the object
     * @throws NotPermittedException if the user lacks EDIT permissions for the object
     * @since 2.0
     */
    boolean addLabelById(String token, long labelId, long objectId) throws NotPermittedException, InvalidSessionException, RemoteException;

    /**
     * Adds the given label object to the object with the given ContentEntityObject ID.
     *
     * @param token       The token identifying the current user
     * @param labelObject The label to be added to the ContentEntityObject
     * @param objectId    The ID of the ContentEntityObject the method will act on
     * @return True if successfully added, false otherwise.
     * @throws RemoteException       if the given RemoteLabel object is null
     * @throws RemoteException       if a Label could not be retrieved for the given ID
     * @throws RemoteException       if the object was not valid
     * @throws RemoteException       if the user lacks VIEW permissions for the object
     * @throws NotPermittedException if the user lacks EDIT permissions for the object
     * @since 2.0
     */
    boolean addLabelByObject(String token, RemoteLabel labelObject, long objectId) throws NotPermittedException, InvalidSessionException, RemoteException;

    /**
     * Adds a label to the object with the given ContentEntityObject ID.
     *
     * @param token     The token identifying the current user
     * @param labelName The name of the label(s) to be added to the Space, in the form of a space-separated string
     * @param spaceKey  The Space to add the label to
     * @return True if successfully added, false otherwise.
     * @throws RemoteException       if the label name is null or an empty String
     * @throws RemoteException       if the split label name is invalid (as determined by LabelUtil.split())
     * @throws RemoteException       if the space does not exist, or the user does not have VIEW permissions
     * @throws RemoteException       if the label could not be created
     * @throws NotPermittedException if the user does not have permission to add the label
     * @since 2.0
     */
    boolean addLabelByNameToSpace(String token, String labelName, String spaceKey) throws NotPermittedException, InvalidSessionException, RemoteException;

    /**
     * Removes the given label from the object with the given ContentEntityObject ID.
     *
     * @param token     The token identifying the current user
     * @param labelName The name of the label(s) to be removed from the ContentEntityObject, in the form of a space-separated String
     * @param objectId  The ID of the ContentEntityObject the method will act on
     * @return True if successfully removed, false otherwise.
     * @throws RemoteException       if the label name is null
     * @throws RemoteException       if the label name is an empty String
     * @throws RemoteException       if one of the given label names does not exist (occurs before removing labels)
     * @throws RemoteException       if the object was not valid
     * @throws RemoteException       if the  user lacks VIEW permissions for the object
     * @throws NotPermittedException if the user lacks EDIT permissions for the object
     * @since 2.0
     */
    boolean removeLabelByName(String token, String labelName, long objectId) throws NotPermittedException, InvalidSessionException, RemoteException;

    /**
     * Removes the label with the given ID from the object with the given ContentEntityObject ID.
     *
     * @param token    The token identifying the current user
     * @param labelId  The ID of the label to be removed from the ContentEntityObject
     * @param objectId The ID of the ContentEntityObject the method will act on
     * @return True if successfully removed, false otherwise.
     * @throws RemoteException       if a Label could not be retrieved for the given ID
     * @throws RemoteException       if the object was not valid
     * @throws RemoteException       if the user lacks VIEW permissions for the object
     * @throws NotPermittedException if the user lacks EDIT permissions for the object
     * @since 2.0
     */
    boolean removeLabelById(String token, long labelId, long objectId) throws NotPermittedException, InvalidSessionException, RemoteException;

    /**
     * Removes the given label object from the object with the given ContentEntityObject ID.
     *
     * @param token       The token identifying the current user
     * @param labelObject The label to be removed from the ContentEntityObject
     * @param objectId    The ID of the ContentEntityObject the method will act on
     * @return True if successfully removed, false otherwise.
     * @throws RemoteException       if the RemoteLabel object is null
     * @throws RemoteException       if a Label could not be retrieved for the given ID
     * @throws RemoteException       if the object was not valid
     * @throws RemoteException       if the user lacks VIEW permissions for the object
     * @throws NotPermittedException if the user lacks EDIT permissions for the object
     * @since 2.0
     */
    boolean removeLabelByObject(String token, RemoteLabel labelObject, long objectId) throws NotPermittedException, InvalidSessionException, RemoteException;

    /**
     * Removes the given label from the given Space
     *
     * @param token     The token identifying the current user
     * @param labelName The name of the label(s) to be removed from the Space, in the form of a space-separated String
     * @param spaceKey  The Space the method will act on
     * @return True if successfully removed, false otherwise.
     * @throws RemoteException       if the label name is null
     * @throws RemoteException       if the label name is an empty String
     * @throws RemoteException       if one of the given label names does not exist (occurs before removing labels)
     * @throws RemoteException       if the space does not exist, or the user lacks VIEW permissions
     * @throws NotPermittedException if the user lacks EDIT permissions for the Space
     * @since 2.0
     */
    boolean removeLabelByNameFromSpace(String token, String labelName, String spaceKey) throws NotPermittedException, InvalidSessionException, RemoteException;
}