//  Diffusion Client Library for iOS, tvOS and OS X / macOS
//
//  Copyright (c) 2018 - 2025 DiffusionData Ltd., All Rights Reserved.
//
//  Use is subject to licence terms.
//
//  NOTICE: All information contained herein is, and remains the
//  property of DiffusionData. The intellectual and technical
//  concepts contained herein are proprietary to DiffusionData and
//  may be covered by U.S. and Foreign Patents, patents in process, and
//  are protected by trade secret or copyright law.

#import <Foundation/Foundation.h>
#import <Diffusion/PTDiffusionFeature.h>

@class PTDiffusionRegistration;
@class PTDiffusionSessionId;
@class PTDiffusionStream;
@class PTDiffusionTopicSelection;


NS_ASSUME_NONNULL_BEGIN

/**
 The value assigned to the `domain` property of NSError objects generated by the
 PTDiffusionSubscriptionControlFeature.

 @since 6.1
 */
extern NSString *const PTDiffusionSubscriptionControlFeatureErrorDomain __deprecated_msg("Use PTDiffusion instead.");

/**
 @ingroup PublicAPI_SubscriptionControl

 @brief The Subscription Control feature allows a client session to subscribe
 or unsubscribe other sessions to topics, on a single server or across a cluster.

 The Subscription Control feature for a session can be obtained from the
 session's `PTDiffusionSession#subscriptionControl` property.

 Requests to subscribe sessions to topics can be submitted at any time even if
 the topics do not exist at the server. @ref md_topic_selectors "Topic selectors"
 are used on subscription to match against topics at the server. The session
 will become subscribed to any topics that exist at the server that match the
 selector (unless they are already subscribed, or the session has insufficient
 permission). The subscription request is also retained at the server so that if
 any newly created topics match the selector, the session will then become
 subscribed to it (unless a subsequent unsubscription cancels it).

 Specific sessions (anywhere in a cluster) may be subscribed/unsubscribed if the PTDiffusionSessionId is
 known.

 Subscriptions may also be requested using
 @ref md_session_filters "session filters", where all sessions (anywhere in a cluster) that satisfy a
 particular filter expression will be subscribed/unsubscribed. The filter is
 only evaluated once against the current sessions that exist at the time - it is
 not retained and applied to any sessions that are created later. In order to be
 notified of new sessions as they are created a
 PTDiffusionSessionPropertiesListener can be used and those sessions subscribed
 as required based upon their session properties.

 ### Access control

 To subscribe or unsubscribe other sessions to topics, a session must have
 `PTDiffusionGlobalPermission#modifySession` permission, and
 `PTDiffusionPathPermission#selectTopic` permission for the topic selector used.
 The subscribed sessions will only be subscribed to matching topics for
 which they have `PTDiffusionPathPermission#readTopic` permission.

 To unsubscribe other sessions, a session must have `PTDiffusionGlobalPermission#modifySession` permission.

 @since 6.1
 */
@interface PTDiffusionSubscriptionControlFeature : PTDiffusionFeature


/**
 @brief Subscribe another session to topics.

 New subscriptions will be established for existing topics that match the provided topic selector
 and for which the subscribed session has `PTDiffusionPathPermission.readTopic` permission.
 The topic selector will be added to the topic selections of the subscribed session, and re-evaluated when new
 topics are added or the session's security roles change.

 A session that does not have `PTDiffusionPathPermission.selectTopic` permission for a topic
 cannot subscribe directly, but can be subscribed indirectly using this method.

 @param sessionId Identifies the session to subscribe.

 @param expression The @ref md_topic_selectors "topic selector" expression to be
 evaluated by the server, identifying the topics to subscribe to.

 @param selectionScope specifies the scope of the selection.

 @param completionHandler Block to be called asynchronously on success or
 failure. If the operation was successful, the `error` argument passed to the
 block will be `nil`. The completion handler will be called asynchronously on
 the main dispatch queue.

 @return error if any supplied arguments are `nil` or invalid. `nil` otherwise.

 @since 6.12
 */
-(nullable NSError *) subscribe:(PTDiffusionSessionId *)sessionId
                             to:(NSString *)expression
             withSelectionScope:(NSString *)selectionScope
              completionHandler:(void (^)(NSError * _Nullable error))completionHandler;


/**
 Subscribe another session to topics.

 This is equivalent to calling `subscribe:to:withSelectionScope:completionHandler:` specifying the
`PTDiffusionTopicsFeature.defaultSelectionScope` as the selection scope.

 @param sessionId Identifies the session to subscribe.

 @param expression The @ref md_topic_selectors "topic selector" expression to be
 evaluated by the server, identifying the topics to subscribe to.

 @param completionHandler Block to be called asynchronously on success or
 failure. If the operation was successful, the `error` argument passed to the
 block will be `nil`. The completion handler will be called asynchronously on
 the main dispatch queue.

 @since 6.1
 */
-(void)      subscribeSessionId:(PTDiffusionSessionId *)sessionId
    withTopicSelectorExpression:(NSString *)expression
              completionHandler:(void (^)(NSError * _Nullable error))completionHandler;



/**
 @brief Unsubscribe another session from topics.

 This function requests that a client (anywhere in a cluster) is unsubscribed from the
 topics specified by a topic selector.

 @param sessionId Identifies the session to subscribe.

 @param expression The @ref md_topic_selectors "topic selector" expression to be
 evaluated by the server, identifying the topics to subscribe to.

 @param selectionScope specifies the scope of the selection.

 @param completionHandler Block to be called asynchronously on success or
 failure. If the operation was successful, the `error` argument passed to the
 block will be `nil`. The completion handler will be called asynchronously on
 the main dispatch queue.

 @return error if any supplied arguments are `nil` or invalid. `nil` otherwise.

 @since 6.12
 */
-(nullable NSError *) unsubscribe:(PTDiffusionSessionId *)sessionId
                             from:(NSString *)expression
               withSelectionScope:(NSString *)selectionScope
                completionHandler:(void (^)(NSError * _Nullable error))completionHandler;


/**
 Unsubscribe another session from topics.

 @param sessionId Identifies the session to unsubscribe.

 @param expression The @ref md_topic_selectors "topic selector" expression to be
 evaluated by the server, identifying the topics to unsubscribe from.

 @param completionHandler Block to be called asynchronously on success or
 failure. If the operation was successful, the `error` argument passed to the
 block will be `nil`. The completion handler will be called asynchronously on
 the main dispatch queue.

 @since 6.1
 */
-(void)    unsubscribeSessionId:(PTDiffusionSessionId *)sessionId
    withTopicSelectorExpression:(NSString *)expression
              completionHandler:(void (^)(NSError * _Nullable error))completionHandler;


/**
 @brief Unsubscribe topics from all topic selection scopes.

 This can be used at any time whilst connected to reduce the set of topics
 to which the session is subscribed or negate earlier subscription
 requests and will apply to all scopes in use.

 @param sessionId Identifies the session to subscribe.

 @param expression The @ref md_topic_selectors "topic selector" expression to be
 evaluated by the server, identifying the topics to subscribe to.

 @param completionHandler Block to be called asynchronously on success or
 failure. If the operation was successful, the `error` argument passed to the
 block will be `nil`. The completion handler will be called asynchronously on
 the main dispatch queue.

 @return error if any supplied arguments are `nil` or invalid. `nil` otherwise.

 @since 6.12
 */
-(nullable NSError *) unsubscribeAllScopes:(PTDiffusionSessionId *)sessionId
                                      from:(NSString *)expression
                         completionHandler:(void (^)(NSError * _Nullable error))completionHandler;


/**
 @brief Subscribe sessions that satisfy a given session filter to topics.
 In a clustered environment the filter will be applied to all servers in the cluster.

 For each session (anywhere in a cluster) that matches the filter, new subscriptions will be
 established for existing topics that match the provided topic selector
 and for which the sessions has `PTDiffusionPathPermission.readTopic` permission.
 The topic selector will be added to the topic selections of the subscribed session,
 and re-evaluated when new topics are added or the session's security roles change.

 A session that does not have `PTDiffusionPathPermission.selectTopic` permission for a topic
 cannot subscribe directly, but can be subscribed indirectly using this method.

 @param sessionId Identifies the session to subscribe.

 @param expression The @ref md_topic_selectors "topic selector" expression to be
 evaluated by the server, identifying the topics to subscribe to.

 @param selectionScope specifies the scope of the selection.

 @param completionHandler Block to be called asynchronously on success or
 failure. If the operation was successful, the `error` argument passed to the
 block will be `nil`. The completion handler will be called asynchronously on
 the main dispatch queue.

 @return error if any supplied arguments are `nil` or invalid. `nil` otherwise.

 @since 6.12
 */
-(nullable NSError *) subscribeWithFilter:(NSString *)filter
                                       to:(NSString *)expression
                       withSelectionScope:(NSString *)selectionScope
                        completionHandler:(void (^const)(NSUInteger, NSError * _Nullable))completionHandler;


/**
 @brief Subscribe sessions that satisfy a given session filter to topics.
 In a clustered environment the filter will be applied to all servers in the cluster.

 This is equivalent to calling `subscribeWithFilter:to:withSelectionScope:completionHandler:` specifying the
 `PTDiffusionTopicsFeature.defaultSelectionScope` as the selection scope.

 @param filter The @ref md_session_filters "session filter" expression.

 @param expression The @ref md_topic_selectors "topic selector" expression to be
 evaluated by the server, identifying the topics to subscribe to.

 @param completionHandler Block to be called asynchronously on success or
 failure. If the operation was successful, the `error` argument passed to the
 block will be `nil` and the `count` argument indicates the number of clients
 that satisfied the filter and qualified for subscription. On failure the
 `error` argument passed to the block will not be `nil` and the `count` argument
 will be zero. The completion handler will be called asynchronously on the main
 dispatch queue.

 @note The completion handler block will be invoked with a `nil` for the `error`
 argument and zero for the `count` argument if no client sessions satisfied the
 filter.

 @since 6.1
 */
-(void) subscribeWithFilter:(NSString *)filter
    topicSelectorExpression:(NSString *)expression
          completionHandler:(void (^)(NSUInteger count, NSError * _Nullable error))completionHandler;


/**
 @brief Unsubscribe sessions (anywhere in a cluster) that satisfy a given session filter from topics.

 @param sessionId Identifies the session to subscribe.

 @param expression The @ref md_topic_selectors "topic selector" expression to be
 evaluated by the server, identifying the topics to subscribe to.

 @param selectionScope specifies the scope of the selection.

 @param completionHandler Block to be called asynchronously on success or
 failure. If the operation was successful, the `error` argument passed to the
 block will be `nil`. The completion handler will be called asynchronously on
 the main dispatch queue.

 @return error if any supplied arguments are `nil` or invalid. `nil` otherwise.

 @since 6.12
 */
-(nullable NSError *) unsubscribeWithFilter:(NSString *)filter
                                       from:(NSString *)expression
                         withSelectionScope:(NSString *)selectionScope
                          completionHandler:(void (^const)(NSUInteger, NSError * _Nullable))completionHandler;


/**
 @brief Unsubscribe sessions (anywhere in a cluster) that satisfy a given session filter from topics.

 This is equivalent to calling `unsubscribeWithFilter:from:withSelectionScope:completionHandler:` specifying the
 `PTDiffusionTopicsFeature.defaultSelectionScope` as the selection scope.

 @param filter The @ref md_session_filters "session filter" expression.

 @param expression The @ref md_topic_selectors "topic selector" expression to be
 evaluated by the server, identifying the topics to unsubscribe from.

 @param completionHandler Block to be called asynchronously on success or
 failure. If the operation was successful, the `error` argument passed to the
 block will be `nil` and the `count` argument indicates the number of clients
 that satisfied the filter and qualified for unsubscription. On failure the
 `error` argument passed to the block will not be `nil` and the `count` argument
 will be zero. The completion handler will be called asynchronously on the main
 dispatch queue.

 @note The completion handler block will be invoked with a `nil` for the `error`
 argument and zero for the `count` argument if no client sessions satisfied the
 filter.

 @since 6.1
 */
-(void)unsubscribeWithFilter:(NSString *)filter
     topicSelectorExpression:(NSString *)expression
           completionHandler:(void (^)(NSUInteger count, NSError * _Nullable error))completionHandler;


/**
 @brief Unsubscribe topics from all topic selection scopes.

 Unsubscribe sessions that satisfy a given session filter from topics for
 all scopes. In a clustered environment the filter will be applied to all
 servers in the cluster.

 @param filter The @ref md_session_filters "session filter" expression.

 @param expression The @ref md_topic_selectors "topic selector" expression to be
 evaluated by the server, identifying the topics to subscribe to.

 @param completionHandler Block to be called asynchronously on success or
 failure. If the operation was successful, the `error` argument passed to the
 block will be `nil`. The completion handler will be called asynchronously on
 the main dispatch queue.

 @return error if any supplied arguments are `nil` or invalid. `nil` otherwise.

 @since 6.12
 */
-(nullable NSError *) unsubscribeAllScopesWithFilter:(NSString *)filter
                                                from:(NSString *)expression
                                   completionHandler:(void (^const)(NSUInteger, NSError * _Nullable))completionHandler;


/**
 @brief Returns a map of the current topic selection state for a specified session, keyed on topic selection scope.

 Each scope will have an ordered list of selections and/or deselections.

 The server conflates selections, so if there has been a selection that is later rendered redundant
 by a deselection it will not be present.
 A scope that has been used but fully deselected will therefore not be present in the map and
 therefore no entry will have an empty list.

 If the session has no current selections the map will be empty.

 @since 6.12
 */
-(nullable NSError *) getTopicSelections:(PTDiffusionSessionId *)sessionId
                       completionHandler:(void (^)(NSDictionary<NSString *, NSArray<PTDiffusionTopicSelection *> *> *result, NSError * _Nullable error))completionHandler;

@end

NS_ASSUME_NONNULL_END
