//
// © 2018-2020 Qualcomm Technologies, Inc. and/or its subsidiaries. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "IoTTypes.h"

NS_ASSUME_NONNULL_BEGIN

@class IoTPlayer;
@class IoTPlaylist;
@class IoTMediaItem;
@class IoTInputOutputSelector;

/**
 @brief A representation of a group member. The member may not be present on the network and so would not have a corresponding IoTPlayer instance.
*/
@interface IoTPlayerGroupMember : NSObject

/**
 @brief The playerID of the player. This would be identical to the playerID of the corresponding IoTPlayer is present.
*/
@property (nonatomic, readonly) NSString *playerID;

/**
 @brief The name of the player. This would be identical to the name of the corresponding IoTPlayer is present. If not it is the last known name.
 */
@property (nonatomic, readonly) NSString *displayName;

/**
 @brief Is the member currently present on the network.
 */
@property (nonatomic, readonly) BOOL available;

@end

/**
 @brief A representation for a group of players.
 @discussion Players can either be grouped or ungrouped - both are represented by IoTPlayerGroups. For "ungrouped" players (meaning those not in groups reported by the AllPlay services on the speakers) a "convenience" group is created by the controller SDK for each player individually. A Player can only be a member of one group.

 	 There is no publicly accessible initializer for IoTPlayerGroup
 */
@interface IoTPlayerGroup : NSObject

- (instancetype)init NS_UNAVAILABLE;

/**
 @brief Is unique ID for the group
 @discussion For convenience groups (namely those created for otherwise ungrouped players), the groupID is the same as the playerID for the player.
 */
@property (nonatomic, readonly) NSString *groupID;

/**
 @brief Is the group one created for a single "ungrouped" speaker.
 @discussion In AllPlay players can be ungrouped. As a convenience to the UI layer, these players are added to special groups of their own - convenience groups. However, as the AllPlay layer does not know about these groups, they should not be passed to APIs that expect non-convenience groups.
 */
@property (nonatomic, readonly) BOOL isConvenienceGroup;

/**
 @brief The player currently used as the source for audio by the group. This can change at any time.
 */
@property (nonatomic, readonly, nullable) NSString *sourcePlayerID;

/**
 @brief The members of the group regardless of if they are present on the network.
 */
@property (nonatomic, readonly) NSArray<IoTPlayerGroupMember *> *members;

/**
 @brief The playlist that is being used by the group
 @discussion When the group is streaming audio from a playlist, this is the playlist on the source player (see sourcePlayerID). In other situations, the playlist may be nil.
 */
@property (nonatomic, readonly, nullable) IoTPlaylist *playlist;

/**
 @brief The active input source for the group.
 @discussion When the group is not streaming audio from a playlist, this is the active input selector on the source player (see sourcePlayerID). In other situations, the activeInputSelector may be nil.
 */
@property (nonatomic, readonly, nullable) IoTInputOutputSelector *activeInputSelector;

/**
 @brief The active output sinks for the group.
 @discussion These are a coalesced array of the active output selectors on all the present players in the group.
 */
@property (nonatomic, readonly) NSArray<IoTInputOutputSelector *> *activeOutputSelectors;

/**
 @brief Are any players in the group available.
 */
@property (nonatomic, readonly) BOOL available;

/**
 @brief The human readable name for the group.
 */
@property (nonatomic, readonly) NSString *displayName;

#pragma mark Volume Management

/**
 @brief Denotes whether a group allows modification of volume.
 */
@property (nonatomic, readonly) BOOL isVolumeEnabled;

/**
 @brief The maximum allowable volume that can be set.
 */
@property (nonatomic, readonly) double maxVolume;

/**
 @brief The current volume for this group.
 */
@property (nonatomic, readonly) double volume;

/**
 @brief The current mute state for this group.
 @discussion The mute state of the group reflects the mute state of the individual players. If any of the players in the group is not muted then the group as a whole is deemed not to be muted.
 */
@property (nonatomic, readonly) BOOL isMuted;

/**
 @brief Asynchronously dispatch request to set the volume of the group.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param volume the requested volume. Usually a value between zero and one.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)setVolume:(double)volume
       completion:(nullable IoTCompletionHandler)completion
  completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to set mute state of the group.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param mute the new desired mute state.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)setMuted:(BOOL)mute
      completion:(nullable IoTCompletionHandler)completion
 completionQueue:(nullable dispatch_queue_t)queue;

#pragma mark Enabled Controls

/**
 @brief Does the group (through its current source player) support seek operations.
 */
@property (nonatomic, readonly) BOOL isSeekEnabled;

/**
 @brief Does the group (through its current source player) support skipping to a next song.
 */
@property (nonatomic, readonly) BOOL isNextEnabled;

/**
 @brief Does the group (through its current source player) support skipping to a previous song.
 */
@property (nonatomic, readonly) BOOL isPreviousEnabled;

/**
 @brief Does the group (through its current source player) support pause/resume.
 */
@property (nonatomic, readonly) BOOL isPauseEnabled;

/**
 @brief Denotes whether a player is interruptible. Depends on source.
 */
@property (nonatomic, readonly) BOOL isInterruptible;

#pragma Media Control

/**
 @brief The current playing status of the player (playing, paused, stopped or buffering).
 */
@property (nonatomic, readonly) IoTPlayState playState;

/**
 @brief The current playhead position within a track in milliseconds.
 @discussion This value is maintained by the controller SDK as a convenience to the UI layer. The AllPlay API does not continuously update the playing
 	position - it is only updated upon a state change. Internally the controller SDK maintains an offset to this notified value and this offset is added to
	the AllPlay reported value to provide a reasonably accurate value via this parameter.
 */
@property (nonatomic, readonly) int playerPosition;

/**
 @brief Asynchronously dispatch request to move the playhead position (seek).
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param position the new desired playhead position (in milliseconds).
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)setPlayerPosition:(int)position
               completion:(nullable IoTCompletionHandler)completion
          completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to play a specific media item.
 @discussion In practice, this method is *not used* by the UI layer. Instead, the UI layer adds the media item to the group's playlist and requests that the newly added item is played with reference to it's index within the playlist.
 @param mediaItem the media item to play.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)playMediaItem:(IoTMediaItem *)mediaItem
           completion:(nullable IoTCompletionHandler)completion
      completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to resume playback of a paused track.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)playWithCompletion:(nullable IoTCompletionHandler)completion
           completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to pause playback of a playing track.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)pauseWithCompletion:(nullable IoTCompletionHandler)completion
            completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to stop (as opposed to pause) playback of a playing track.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)stopWithCompletion:(nullable IoTCompletionHandler)completion
           completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to start playing the next track in the group's playlist.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)nextWithCompletion:(nullable IoTCompletionHandler)completion
           completionQueue:(nullable dispatch_queue_t)queue;

/**
 @brief Asynchronously dispatch request to start playing the previous track in the group's playlist.
 @discussion The completion block notes the request as successful if the POST succeeds. It does not ensure that the request was effected.
 @param completion block to be called asynchronously upon completion (successful or otherwise).
 @param queue the dispatch queue to use when calling the completion block.
 */
- (void)previousWithCompletion:(nullable IoTCompletionHandler)completion
               completionQueue:(nullable dispatch_queue_t)queue;

@end

NS_ASSUME_NONNULL_END
