//
//  OTPublisherKit.h
//
//  Copyright (c) 2014 Tokbox, Inc. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#import <OpenTok/OTVideoKit.h>
#import <OpenTok/OTAudioKit.h>
#import "OpenTok/OTVideoEventReason.h"

@class OTPublisherKit, OTSession, OTError, OTStream, OTPublisherKitVideoNetworkStats, OTPublisherKitAudioNetworkStats,
OTPublisherKitMediaLinkStats;

@protocol OTVideoCapture;
@protocol OTVideoRender;
@protocol OTPublisherKitDelegate;
@protocol OTPublisherKitAudioLevelDelegate;
@protocol OTPublisherKitNetworkStatsDelegate;
@protocol OTPublisherKitRtcStatsReportDelegate;

/**
* Defines values for the <[OTPublisherKit videoType]> property.
*/
typedef NS_ENUM(int32_t, OTPublisherKitVideoType) {
    /**
     * Defines the camera video mode setting for the
     * <[OTPublisherKit videoType]> property.
     */
    OTPublisherKitVideoTypeCamera = 1,
    /**
     * Defines the screen video mode setting for the
     * <[OTPublisherKit videoType]> property.
     */
    OTPublisherKitVideoTypeScreen = 2,
};

/**
 * Preset strategies for controlling video bitrate in a publisher's stream.
 *
 * These presets allow applying predefined bandwidth strategies without manually
 * specifying bitrates. Presets are mutually exclusive with manual bitrate configuration.
 *
 * See <[OTPublisherKit videoBitratePreset]> and
 * <a target="_top" href="https://tokbox.com/developer/guides/publisher-max-bitrate/ios/">Publisher Max Bitrate</a>.
 */
typedef NS_ENUM(NSInteger, OTVideoBitratePreset) {
    
    /**
     * Default preset. No extra restrictions are applied.
     *
     * This is the default mode.
     */
    OTVideoBitratePresetDefault = 0,
    
    /**
     * Bandwidth saver preset.
     *
     * Applies moderate constraints to reduce bandwidth usage while
     * maintaining reasonable video quality.
     */
    OTVideoBitratePresetBwSaver = 1,
    
    /**
     * Extra bandwidth saver preset.
     *
     * Applies aggressive constraints to minimize bandwidth usage.
     */
    OTVideoBitratePresetExtraBwSaver = 2,
    
    /**
     * Custom bitrate.
     *
     * Represents a manually configured bitrate set using <code>maxVideoBitrate</code>.
     * This value is returned for tracking purposes but cannot be set directly.
     * Setting <code>maxVideoBitrate</code> overrides any preset and switches this
     * property to <code>OTVideoBitratePresetCustom</code>.
     */
    OTVideoBitratePresetCustom = 3
};

/**
 * Define values for the <[OTVideoCodecPreference codecs]> property as well as items in the array used by the <[OTVideoCodecPreference manualWithCodecs:]> method.
 */
typedef NS_ENUM(NSInteger, OTVideoCodecType) {
    /**
     * Video codec type for VP8.
     */
    OTVideoCodecTypeVP8  = 1,

    /**
     * Video codec type for H264.
     */
    OTVideoCodecTypeH264 = 2,

    /**
     * Video codec type for VP9.
     */
    OTVideoCodecTypeVP9  = 3
};

/**
 * @brief Describes the policy that the video engine will try to follow when adapting frame rate and resolution to
 * limited bandwidth and CPU. This is a best effort policy. There are no guarantees on the frame rate and some frames can
 * still be skipped for other reasons.
 *
 * For details, see 
 * <a target="_top" href="https://w3c.github.io/webrtc-pc/#idl-def-rtcdegradationpreference/">Degradation
 * Preference</a>.
 */
typedef NS_ENUM(NSInteger, OTDegradationPreference) {
    
    /**
     * Default value. The video engine will decide the optimal degradation preference.
     */
    OTDegradationPreferenceNotSet = -1,
    
    /**
     * The video engine will not reduce the resolution and will try to keep the frame rate steady.
     * In some versions of the standard this option is referred to as "DISABLED", meaning that no degradation will be
     * applied at all when under limited resources.
     */
    OTDegradationPreferenceMaintainFrameRateAndResolution = 0,
    
    /**
     * The video engine will try to keep the frame rate steady but might reduce resolution if necessary.
     */
    OTDegradationPreferenceMaintainFrameRate = 1,
    
    /**
     * The video engine will not reduce the resolution but might reduce the frame rate if necessary.
     */
    OTDegradationPreferenceMaintainResolution = 2,
    
    /**
     * The video engine will try to reach a balance between reducing resolution and frame rate when necessary.
     */
    OTDegradationPreferenceBalanced = 3
};


/**
 * @class OTVideoCodecPreference
 * @brief Defines the codec preference for video publishing.
 *
 * This class allows you to specify whether the SDK should automatically
 * select the best video codec or if you want to explicitly provide a list
 * of preferred codecs. It is used when configuring publishers to control
 * which codecs are prioritized during negotiation. If it's not used, the
 * codec specified in the project settings will have priority.
 */
@interface OTVideoCodecPreference : NSObject

/**
 * Indicates whether codec selection is automatic.
 *
 * - If `YES`, the SDK will automatically choose the most suitable codec.
 * - If `NO`, you must provide a list of codecs in `codecs`.
 */
@property (nonatomic, readonly) BOOL automatic;

/**
 * Ordered list of preferred codecs.
 *
 * This property is only valid when `automatic == NO`.
 * The array contains `NSNumber` values representing codec types. See <OTVideoCodecType>.
 */
@property (nonatomic, readonly, nonnull) NSArray<NSNumber *> *codecs;

/**
 * Creates a codec preference where the SDK automatically selects the codec.
 *
 * @return A new instance of OTVideoCodecPreference configured for automatic codec selection.
 */
+ (nonnull instancetype)automatic;

/**
 * Creates a codec preference with an explicit list of codecs.
 *
 * @param codecs An ordered array of codec types (wrapped in NSNumber), indicating the preferred order of codec negotiation. See <OTVideoCodecType>.
 * @return A new instance of <OTVideoCodecPreference> configured with the given codec list.
 */
+ (nonnull instancetype)manualWithCodecs:(nonnull NSArray<NSNumber *> *)codecs;

- (nonnull instancetype)init __attribute__((unavailable("Use +automatic or +manualWithCodecs:")));
+ (nonnull instancetype)new __attribute__((unavailable("Use +automatic or +manualWithCodecs:")));

@end

/**
 * Defines settings to be used when initializing a publisher using the
 * <[OTPublisherKit initWithDelegate:settings:]> method.
 */
@interface OTPublisherKitSettings : NSObject

/** @name Defining publisher settings */

/**
 * The name of the publisher video. The <[OTStream name]> property
 * for a stream published by this publisher will be set to this value
 * (on all clients). The default value is `nil`.
 */
@property(nonatomic, copy, nullable) NSString *name;

/**
 * Whether to publish audio (YES, the default) or not (NO).
 *
 * If this property is set to NO, the audio subsystem will not be initialized
 * for the publisher, and setting the <[OTPublisherKit publishAudio]> property
 * will have no effect. If your application does not require the use of audio,
 * it is recommended to set this Builder property rather than use the
 * <[OTPublisherKit publishAudio]> property, which only temporarily disables
 * the audio track.
 */
@property(nonatomic) BOOL audioTrack;

/**
 * Whether to publish video (YES, the default) or not (NO).
 *
 * If this property is set to NO, the video subsystem will not be initialized
 * for the publisher, and setting the <[OTPublisherKit publishVideo]> property
 * will have no effect. If your application does not require the use of video,
 * it is recommended to set this Builder property rather than use the
 * <[OTPublisherKit publishVideo]> property, which only temporarily disables
 * the video track.
 */
@property(nonatomic) BOOL videoTrack;

/**
 * Whether to publish sender statistics (YES) or not (NO, the default).
 *
 * If this property is set to NO, the sender statistics subsystem will not be initialized
 * for the publisher.
 */
@property(nonatomic) BOOL senderStatsTrack;

/**
 * The desired bitrate for the published audio, in bits per second.
 * The supported range of values is 6,000 - 510,000. (Invalid values are
 * ignored.) Set this value to enable high-quality audio (or to reduce
 * bandwidth usage with lower-quality audio).
 *
 * The following are recommended settings:
 *
 * * 8,000 - 12,000 for narrowband (NB) speech
 * * 16,000 - 20,000 for wideband (WB) speech
 * * 28,000 - 40,000 for full-band (FB) speech
 * * 48,000 - 64,000 for full-band (FB) mono music
 * * 64,000 - 128,000 for full-band (FB) stereo music
 *
 * The default value is 40,000.
 *
 * To set other audio settings, see the <OTAudioDeviceManager> interface.
 */
@property(nonatomic) int audioBitrate;

/**
 * Whether to enable [Opus DTX](https://datatracker.ietf.org/doc/html/rfc7587#section-3.1.3)
 * (YES) or not (NO, the default). Enabling Opus DTX can reduce bandwidth usage
 * in streams that have long periods of silence.
 */
@property(nonatomic) BOOL enableOpusDtx;

/**
 * Whether to allow use of
 * <a href="https://tokbox.com/developer/guides/scalable-video/">scalable video</a>
 * for a publisher that has the videoType
 * set to OTStreamVideoTypeScreen (YES) or not (NO, the default).
 */
@property(nonatomic) BOOL scalableScreenshare;

/**
 * Whether the stream will use the subscriber audio-fallback feature (<code>YES</code>) or
 * not (<code>NO</code>), for subscribers to the published stream. The subscriber
 * audio-fallback feature is available in sessions that use the the OpenTok Media Router.
 * With the subscriber audio-fallback feature enabled, when the OpenTok
 * Media Router determines that a stream's quality has degraded significantly
 * for a specific subscriber, it disables the video in that subscriber in order to
 * preserve call quality.
 *
 * The default setting is <code>YES</code> (the audio-fallback feature is
 * enabled) for publishers using the camera. When using the
 * screen video type in a session that uses the OpenTok Media Server, the
 * subscriber audio-fallback property is set to <code>NO</code> by default,
 * so that the video does not drop out in subscribers.
 *
 * For more information, see <[OTPublisherKit videoType]>,
 * <[OTSubscriberKitDelegate subscriberVideoDisabled:reason:]>,
 * <OTSubscriberVideoEventReason>, [the OpenTok Media
 * Router](http://tokbox.com/opentok/tutorials/create-session/#media-mode ).
 */
@property (nonatomic, assign) BOOL subscriberAudioFallbackEnabled;

/**
 * Whether the stream will use the publisher audio-fallback feature (<code>YES</code>) or
 * not (<code>NO</code>). With the publisher audio-fallback feature
 * enabled, when the Publisher determines that a stream's quality has
 * degraded significantly, it disables the video in in order to preserve call quality.
 *
 * The default setting is <code>NO</code> (the audio-fallback feature is
 * disabled).
 *
 * For more information, see <[OTPublisherKit videoType]>,
 * <[OTPublisherKitDelegate publisherVideoDisabled:reason:]>,
 * <OTPublisherVideoEventReason>, [the OpenTok Media
 * Router](http://tokbox.com/opentok/tutorials/create-session/#media-mode ).
 *
 */
@property (nonatomic, assign) BOOL publisherAudioFallbackEnabled;

/**
 * If set to NO, the microphone will be automatically switched off when all publishers
 * have muted their audio. Microphone will be automatically switched on again when at least one
 * publisher unmutes their audio.
 * If set to YES, mic will always remain switched on even when all publishers have muted their audio.
 * Be aware that when the microphone is switched off, callbacks like AudioLevel or AudioData
 * will no longer be invoked for the publishers.
 * The default value is NO.
 */
@property(nonatomic) BOOL allowAudioCaptureWhileMuted;

/**
 * Defines the preferred video codec(s) for publishing.
 *
 * Use this property to control which video codecs are prioritized during negotiation.
 * If not set, the SDK uses the project’s default codec preference.
 * Assign an instance of <OTVideoCodecPreference> to specify whether codec selection
 * should be automatic or to provide an explicit, ordered list of codecs.
 *
 * - Set to `[OTVideoCodecPreference automatic]` to allow the SDK to select the most suitable codec.
 * - Set to `[OTVideoCodecPreference manualWithCodecs:...]` to explicitly specify a preferred order
 *   of codec negotiation. Supported codecs: `OTVideoCodecTypeVP8`, `OTVideoCodecTypeH264`, `OTVideoCodecTypeVP9`.
 *
 * If an invalid codec list is provided (e.g., empty array or unknown codec value), publisher initialization will fail.
 *
 * For details on codec selection and valid values, see <OTVideoCodecPreference>.
 */
@property (nonatomic, nullable) OTVideoCodecPreference *videoCodecPreference;
@end

/**
 * A publisher captures an audio-video stream from the sources you specify. You
 * can then publish the audio-video stream to an OpenTok session by sending the
 * <[OTSession publish:error:]> message.
 *
 * The OpenTok iOS SDK supports publishing on all multi-core iOS devices.
 * See "Developer and client requirements" in the README file for the
 * [OpenTok iOS SDK](http://tokbox.com/opentok/libraries/client/ios).
 */
@interface OTPublisherKit : NSObject

- (_Nonnull instancetype)init NS_UNAVAILABLE;

/** @name Initializing a publisher */

/**
 * Initialize a publisher object and specify the delegate object.
 *
 * When running in the XCode iOS Simulator, this method returns `nil`.
 *
 * @param delegate The delegate (<OTPublisherKitDelegate>) object for the
 * publisher.
 *
 * @return The pointer to the instance, or `nil` if initialization failed.
 */
- (nullable instancetype)initWithDelegate:(nullable id<OTPublisherKitDelegate>)delegate;

/**
 * Initialize the publisher with settings defined by an
 * <OTPublisherKitSettings> object.
 *
 * @param delegate The delegate (<OTPublisherKitDelegate>) object for the
 * publisher.
 *
 * @param settings The (<OTPublisherKitSettings>) object that defines settings
 * for the publisher.
 */
-(nullable instancetype)initWithDelegate:(nullable id<OTPublisherKitDelegate>)delegate
                       settings:(nonnull OTPublisherKitSettings *)settings;

/**
 * Initialize a publisher object, and specify the delegate object and the 
 * stream's name.
 *
 * This method is deprecated. Use <[OTPublisherKit initWithDelegate:settings:]>
 * instead.
 *
 * When running in the XCode iOS Simulator, this method returns `nil`.
 *
 * @param delegate The delegate (<OTPublisherKitDelegate>) object for the 
 * publisher.
 *
 * @param name The name of the publisher video. The <[OTStream name]> property
 * for a stream published by this publisher will be set to this value
 * (on all clients).
 *
 * @return The pointer to the instance, or `nil` if initialization failed.
 */
- (nullable instancetype)initWithDelegate:(nullable id<OTPublisherKitDelegate>)delegate
                                    name:(nullable NSString*)name __attribute((deprecated(("Use initWithDelegate: settings: instead"))));

/**
 * Initialize the publisher, and specify whether audio and video will be
 * enabled for this instance.
 *
 * This method is deprecated. Use <[OTPublisherKit initWithDelegate:settings:]>
 * instead.
 *
 * If either audioTrack or videoTrack are set to NO,
 * the respective subsystem will not be initialized, and setting the
 * corresponding <[OTPublisherKit publishAudio]> and
 * <[OTPublisherKit publishVideo]> properties will have no effect.
 *
 * If your application does not require the use of audio or video, it is
 * recommended to set these values rather than use the
 * <[OTPublisherKit publishAudio]> and <[OTPublisherKit publishVideo]>
 * properties, which only temporarily disable the tracks.
 *
 * @param delegate The delegate (<OTPublisherKitDelegate>) object for the
 * publisher.
 *
 * @param name The name of the publisher video. The <[OTStream name]> property
 * for a stream published by this publisher will be set to this value
 * (on all clients).
 *
 * @param audioTrack Whether to publish audio (YES) or not (NO).
 *
 * @param videoTrack Whether to publish video (YES) or not (NO).
 */
- (nullable instancetype)initWithDelegate:(nullable id<OTPublisherKitDelegate>)delegate
                                    name:(nullable NSString*)name
                              audioTrack:(BOOL)audioTrack
                              videoTrack:(BOOL)videoTrack __attribute((deprecated(("Use initWithDelegate: settings: instead"))));

/** @name Getting information about the publisher */

/**
 * The <OTPublisherDelegate> object, which is the delegate for the OTPublisher
 * object.
 *
 * See also <[OTPublisherKit audioLevelDelegate]>,
 * <[OTPublisherKit networkStatsDelegate]>, and
 * <[OTPublisherKit rtcStatsReportDelegate]>.
 */
@property(nonatomic, weak) id<OTPublisherKitDelegate> _Nullable delegate;

/**
 * Periodically receives reports of audio levels for this publisher.
 *
 * This is a separate delegate object from that set as the delegate property
 * (the OTPublisherKitDelegate object).
 *
 * If you do not set this property, the audio sampling subsystem is disabled.
 */
@property (nonatomic, weak)
id<OTPublisherKitAudioLevelDelegate> _Nullable audioLevelDelegate;

/**
 * The <OTPublisherKitNetworkStatsDelegate> object that periodically
 * receives publisher quality statistics.
 *
 * This delegate object is sent messages reporting the following:
 *
 * * Total audio and video packets lost
 * * Total audio and video packets received
 * * Total audio and video bytes received
 *
 * This is a separate delegate object from that set as the
 * <[OTPublisherKit delegate]> property (the OTPublisherKitDelegate object).
 *
 * Also see <[OTPublisherKit rtcStatsReportDelegate]>.
 */
@property (nonatomic, weak)
id<OTPublisherKitNetworkStatsDelegate> _Nullable networkStatsDelegate;

/**
 * The <OTPublisherKitRtcStatsReportDelegate> that reports RTC stats for
 * the publisher. The <[OTPublisherKitRtcStatsReportDelegate publisher:rtcStatsReport:]>
 * message is sent in reponse to calling the <[OTPublisherKit getRtcStatsReport]>
 * method.
 */
@property (nonatomic, weak)
id<OTPublisherKitRtcStatsReportDelegate> _Nullable rtcStatsReportDelegate;

/**
 * The session that owns this publisher.
 */
@property(readonly) OTSession* _Nullable session;

/**
 * The <OTStream> object associated with the publisher.
 */
@property(readonly) OTStream* _Nullable stream;

/**
 * A string that will be associated with this publisher's stream. This string is
 * displayed at the bottom of subscriber videos associated with the published
 * stream, if an overlay to display the name exists. 
 *
 * The name must be set at initialization, when you when you send the
 * <[OTPublisherKit initWithDelegate:settings:]> message.
 *
 * This value defaults to an empty string.
 */
@property(readonly) NSString* _Nullable name;

/**
 * Gets the RTC stats report for the publisher. This is an asynchronous operation.
 * Set the <[OTPublisherKit rtcStatsReportDelegate]> property and implement the
 * <[OTPublisherKitRtcStatsReportDelegate publisher:rtcStatsReport:]> method
 * prior to calling this method. When the stats are available, the implementation
 * of the <[OTPublisherKitRtcStatsReportDelegate publisher:rtcStatsReport:]>
 * message is sent.
 *
 * Also see <[OTPublisherKit networkStatsDelegate]> and
 * <[OTSubscriberKit getRtcStatsReport]>.
 */
-(void) getRtcStatsReport;

/** @name Controlling audio and video output for a publisher */

/**
 * Whether to publish audio.
 *
 * The default value is TRUE.
 */
@property(nonatomic) BOOL publishAudio;

/**
 * Whether to publish video.
 *
 * The default value is TRUE.
 */
@property(nonatomic) BOOL publishVideo;

/**
 * Whether to make captions active.
 *
 * The default value is FALSE.
 */
@property(nonatomic) BOOL publishCaptions;

/** @name Setting publisher device configuration */

/**
 * The <OTVideoCapture> instance used to capture video to stream to the OpenTok
 * session.
 */
@property(nonatomic, strong) id<OTVideoCapture> _Nullable videoCapture;

/**
 * Specifies the type of video for the published stream.
 *
 * Set this to one of the following values:
 *
 * * <code>OTPublisherKitVideoTypeScreen</code> &mdash; Optimizes the video
 *   encoding for screen sharing. To publish a screen-sharing stream, you
 *   need to implement a custom video capturer for the OTPublisherKit object.
 *   See <[OTPublisherKit videoCapture]>. It is recommended to use a low frame
 *   rate (5 frames per second or lower) with this video type. When using the
 *   screen video type in a session that uses the OpenTok Media Server, the
 *   <OTPublisherKitSettings> audio fallback properties are set to NO by default;
 *   this disables the audio-only fallback feature, so that the video does not
 *   drop out in subscribers. See [the OpenTok Media
 *   Router](http://tokbox.com/opentok/tutorials/create-session/#media-mode ).
 *
 * * <code>OTPublisherKitVideoTypeCamera</code> &mdash;
 *   This is the default setting, which you should use when using a camera
 *   as the video source.
 */
@property (nonatomic, assign) OTPublisherKitVideoType videoType;

/**
 * The <OTVideoRender> instance used to render video to stream to the OpenTok
 * session.
 */
@property(nonatomic, strong) id<OTVideoRender> _Nullable videoRender;

/** @name Controlling the Publisher’s Video Bitrate Preset */

/**
 * The maximum video bitrate for the publisher's video stream, in bits per second (bps).
 *
 * This property sets an explicit upper limit on the publisher’s video bitrate,
 * between 5,000 and 10,000,000. 
 * Setting this property to <code>0</code> clears any manual cap and reverts to 
 * the default preset-based adaptive bitrate behavior with no explicit limit.
 *
 * When reading this property, it returns the currently configured maximum bitrate 
 * in bps. If no manual bitrate has been set, or if a bitrate preset is active, 
 * the value is <code>0</code>.
 *
 * A value of <code>0</code> indicates that no explicit bitrate limit is applied 
 * and the stream operates under adaptive preset rules to optimize quality.
 *
 * Also see <[OTPublisherKit videoBitratePreset]> and
 * <a target="_top" href="https://tokbox.com/developer/guides/publisher-max-bitrate/ios/">Publisher Max Bitrate</a>.
 */
@property(nonatomic) int maxVideoBitrate;

/**
 * The video bitrate preset strategy applied to the publisher's video stream.
 *
 * This property configures a predefined bitrate strategy to balance video quality 
 * and bandwidth usage. Available presets include default behavior, moderate bandwidth 
 * saving, and aggressive bandwidth saving modes. Preset strategies allow control 
 * over encoder behavior without specifying explicit bitrate values.
 *
 * Preset configurations and manual bitrate settings are mutually exclusive. 
 * Setting <code>maxVideoBitrate</code> will override any preset and automatically 
 * change this property’s value to <code>OTVideoBitratePresetCustom</code>.
 *
 * Reading this property returns the currently active preset. If a custom bitrate 
 * has been manually set, the value will be <code>OTVideoBitratePresetCustom</code>.
 *
 * The default value is <code>OTVideoBitratePresetDefault</code>.
 *
 * Also see <[OTPublisherKit maxVideoBitrate]> and
 * <a target="_top" href="https://tokbox.com/developer/guides/publisher-max-bitrate/ios/">Publisher Max Bitrate</a>.
 */
@property(nonatomic) OTVideoBitratePreset videoBitratePreset;

/**
 * The preferred policy that the video engine will follow when adjusting frame rate and resolution to
 * limited bandwidth and CPU conditions. See OTDegradationPreference for a description of the possible values.
 */
@property (nonatomic) OTDegradationPreference degradationPreference;

/**
 * The target scalability mode that was explicitly set via setTargetScalabilityMode:error:.
 * Returns the last value passed to the setter, or null if the setter has never been called.
 * This reflects the user's intent, not the mode actually applied (which may differ due to
 * codec-dependent fallback).
 *
 * This is a beta feature.
 *
 */
@property (nonatomic, readonly) NSString* _Nullable targetScalabilityMode;

/**
 * The target scalability mode (SVC - Scalable Video Coding) for this publisher.
 * The scalability mode controls the number of spatial (resolution) and temporal (frame rate)
 * layers that WebRTC encodes. The mode is applied to the Media Router media path.
 *
 * The setter may be called at any time — it does not require the media path negotiation
 * to have completed. The mode will be applied once the Media Router media path is established.
 *
 * If a non-SVC codec (VP8, H.264) is negotiated on the Media Router media path, the closest
 * applicable mode is used: spatial layers are forced to 1, preserving the temporal dimension
 * (e.g. L2T2 → L1T2 when VP8 is negotiated).
 *
 * @param mode    The desired scalability mode string (e.g. @"L1T3"). Must be one of:
 *                L1T1, L1T2, L1T3, L2T1, L2T2, L2T3, L3T1, L3T2, L3T3.
 * @param error   On failure, set to an OTError with domain OT_PUBLISHER_ERROR_DOMAIN
 *                and code OTPublisherInvalidScalabilityMode.
 */
- (void)setTargetScalabilityMode:(NSString * _Nullable)mode
                           error:(NSError * _Nullable * _Nullable)error;

/** @name Setting media transformers */

/**
 * Array of OTVideoTransformer in the order to be applied to the stream.
 */
@property (nonatomic, strong) NSArray * _Nonnull videoTransformers;

/**
 * Array of OTAudioTransformer in the order to be applied to the stream.
 */
@property (nonatomic, strong) NSArray * _Nonnull audioTransformers;

@end

/**
 * Used for sending messages for an OTPublisher instance. The OTPublisher class
 * includes a `delegate` property. When you send the
 * <[OTPublisherKit initWithDelegate:]> message or the
 * <[OTPublisherKit initWithDelegate:settings:]> message, you specify an
 * OTPublisherKitDelegate object.
 */
@protocol OTPublisherKitDelegate <NSObject>

/**
 * Sent if the publisher encounters an error. After this message is sent,
 * the publisher can be considered fully detached from a session and may
 * be released.
 * @param publisher The publisher that signalled this event.
 * @param error The error (an <OTError> object). The `OTPublisherErrorCode` 
 * enum (defined in the OTError class)
 * defines values for the `code` property of this object.
 */
- (void)publisher:(nonnull OTPublisherKit*)publisher
 didFailWithError:(nonnull OTError*)error;

@optional

/**
 * Sent when a moderator has forced this publisher to mute audio.
 *
 * See <[OTSession forceMuteAll:error:]> and
 * <[OTSession forceMuteStream:error:]>.
 *
 * @param publisher The publisher.
 */
- (void)muteForced:(nonnull OTPublisherKit*)publisher;

/**
 * Sent when the publisher starts streaming.
 *
 * @param publisher The publisher of the stream.
 * @param stream The stream that was created.
 */
- (void)publisher:(nonnull OTPublisherKit*)publisher
    streamCreated:(nonnull OTStream*)stream;

/**
 * Sent when the publisher stops streaming.
 * @param publisher The publisher that stopped sending this stream.
 * @param stream The stream that ended.
 */
- (void)publisher:(nonnull OTPublisherKit*)publisher
  streamDestroyed:(nonnull OTStream*)stream;

/**
 * This message is sent when the publisher stops sending video.
 * Check the reason parameter for the reason why the video stopped.
 *
 * @param publisher The <OTPublisher> that will no longer send video.
 * @param reason The reason that the video track was disabled. See
 * <OTPublisherVideoEventReason>.
 */
- (void)publisherVideoDisabled:(nonnull OTPublisherKit*)publisher
                        reason:(OTPublisherVideoEventReason)reason;

/**
 * This message is sent when the publisher's video stream resumes (after
 * video was disabled). Check the reason parameter for the reason
 * why the video resumed.
 *
 * @param publisher The <OTPublisher> that will send video.
 * @param reason The reason that the video track was enabled. See
 * <OTPublisherVideoEventReason>.
 */
- (void)publisherVideoEnabled:(nonnull OTPublisherKit*)publisher
                       reason:(OTPublisherVideoEventReason)reason;

/**
 * This message is sent when the publisher determines that the stream
 * quality has degraded and the video will be disabled if the quality degrades
 * further. If the quality degrades further, the publisher disables the video
 * and the <[OTPublisherKitDelegate publisherVideoDisabled:reason:]> message
 * is sent. If the network congestion level improves, the
 * <[OTPublisherKitDelegate publisherVideoDisableWarningLifted:]> message is
 * sent.
 *
 * This message is mainly sent when connection quality degrades.
 *
 * @param publisher The <OTPublisher> that may stop sending video soon.
 */
- (void)publisherVideoDisableWarning:(nonnull OTPublisherKit*)publisher;

/**
 * This message is sent when the publisher determines that the network
 * congestion level has improved to the point at which the video being disabled
 * is not an immediate risk. This message is sent after the
 * <[OTPublisherKitDelegate publisherVideoDisableWarning:]> message is
 * sent.
 *
 * This message is mainly sent when connection quality improves.
 *
 * @param publisher The <OTPublisher> instance.
 */
- (void)publisherVideoDisableWarningLifted:(nonnull OTPublisherKit*)publisher;

@end

/**
 * Used for monitoring the audio levels of the publisher.
 */
@protocol OTPublisherKitAudioLevelDelegate <NSObject>

/**
 * Sent on a regular interval with the recent representative audio level.
 *
 * @param publisher The publisher instance being represented.
 * @param audioLevel A value between 0 and 1, representing the audio level.
 * Adjust this value logarithmically for use in a user interface
 * visualization of the volume (such as a volume meter).
 */
- (void)publisher:(nonnull OTPublisherKit*)publisher
audioLevelUpdated:(float)audioLevel;

@end

/**
 * Used to monitor audio and video statistics for the publisher. See
 * <[OTPublisherKit networkStatsDelegate]>.
 */
@protocol OTPublisherKitNetworkStatsDelegate <NSObject>

@optional

/**
 * Sent periodically to report video statistics for the publisher.
 *
 * @param publisher The publisher these statistic apply to.
 *
 * @param stats An array of <OTPublisherKitVideoNetworkStats> objects.
 * For a publisher in a routed session (one that uses the
 * <a href="https://tokbox.com/developer/guides/create-session/#media-mode">OpenTok
 * Media Router</a>), this array includes one object, defining the statistics
 * for the single video media stream that is sent to the OpenTok Media Router.
 * In a relayed session, the array includes an object for each subscriber
 * to the published stream.
 *
 * The <OTPublisherKitVideoNetworkStats> object includes properties.
 * properties for the video bytes received, video packets lost, and video
 * packets sent for the publisher.
 */
- (void)publisher:(nonnull OTPublisherKit*)publisher
videoNetworkStatsUpdated:(nonnull NSArray<OTPublisherKitVideoNetworkStats*>*)stats;

/**
 * Sent periodically to report audio statistics for the publisher.
 *
 * @param publisher The publisher these statistic apply to.
 *
 * @param stats An array of <OTPublisherKitAudioNetworkStats> objects.
 * For a publisher in a routed session (one that uses the
 * <a href="https://tokbox.com/developer/guides/create-session/#media-mode">OpenTok
 * Media Router</a>), this array includes one object, defining the statistics
 * for the single audio media stream that is sent to the OpenTok Media Router.
 * In a relayed session, the array includes an object for each subscriber
 * to the published stream.
 *
 * The <OTPublisherKitAudioNetworkStats> object includes properties.
 * properties for the audio bytes received, audio packets lost, and audio
 * packets sent for the publisher.
 */
- (void)publisher:(nonnull OTPublisherKit*)publisher
audioNetworkStatsUpdated:(nonnull NSArray<OTPublisherKitAudioNetworkStats*>*)stats;


/**
 * Called whenever there is a change in the quality state of the publisher’s video stream.
 *
 * This method provides diagnostic information about video quality changes, including
 * updated statistics and the reason why the event occurred.
 *
 * The `reason` parameter indicates the cause of the event and is considered with the following
 * priority order: bandwidth degradation, CPU degradation, other quality degradation reasons,
 * codec changes, and resolution or video layer changes.
 *
 * Unlike the `publisher:videoEnabled:` and `publisher:videoDisabled:` delegate methods,
 * which indicate that the video track has been turned on or off (for example, due to
 * a stream property update or audio-fallback), this callback reports *quality-related*
 * changes even when video remains enabled. Applications can use this delegate to monitor
 * quality changes and react accordingly—for example, by adjusting UI elements or triggering
 * alerts.
 *
 * @param publisher The publisher whose video stream quality has changed.
 * @param stats Updated video statistics, including details about resolution or video layer changes.
 * @param reason The reason code for the quality change, based on the `OTVideoReason` enum.
 */
- (void)publisher:(nonnull OTPublisherKit *)publisher
videoQualityChanged:(nonnull OTPublisherKitVideoNetworkStats *)stats
           reason:(OTPublisherVideoEventReason)reason;

/**
 * Called whenever a network condition change is detected for the publisher.
 *
 * This callback reports changes in overall network health rather than changes
 * in the publisher’s video track state. It differs from video enabled/disabled
 * callbacks in that it provides diagnostic information about network conditions.
 *
 * Both video and audio statistics are provided to give a complete view of media
 * and network quality. Since audio and video share the same underlying transport,
 * they also share the same local transport and remote participant statistics.
 *
 * The `reason` parameter indicates the cause of the network condition change and
 * is currently reported as `OTNetworkReasonNetworkConditionChange`.
 *
 * Applications can use this callback to react to network issues, such as updating
 * UI indicators, logging telemetry, or triggering adaptive behavior.
 *
 * @param publisher The publisher whose network condition has changed.
 * @param mediaLinkStats The media link statistics.
 * @param reason The reason code for the network condition change.
 */
- (void)publisher:(nonnull OTPublisherKit *)publisher
networkConditionChanged:(nonnull OTPublisherKitMediaLinkStats *)mediaLinkStats
             reason:(OTNetworkReason)reason;

/**
 * Called periodically to report media link statistics for the publisher.
 * It provides transport-level metrics.
 *
 * @param publisher The publisher instance.
 * @param mediaLinkStats The media link statistics.
 */
- (void)publisher:(nonnull OTPublisherKit*)publisher
mediaLinkStatsUpdated:(nonnull NSArray<OTPublisherKitMediaLinkStats*>*)mediaLinkStats;

@end

/**
 * Represents RTC statistics for a media stream published by the publisher.
 *
 * See <[OTPublisherKit getRtcStatsReport]>.
 */
@interface OTPublisherRtcStats : NSObject
/**
 * For a relayed session (in which a publisher sends individual media streams
 * to each subscriber), this is the unique ID of the client's connection.
 */
@property (strong) NSString* _Nonnull connectionId;
/**
  A JSON array of RTC stats reports for the media stream.
  The structure of the JSON array is similar to the format of
  the RtcStatsReport object implemented in web browsers (see
  <a href="https://developer.mozilla.org/en-US/docs/Web/API/RTCStatsReport">Mozilla
  docs</a>). Also see <a href="https://w3c.github.io/webrtc-stats/#summary">this
  W3C documentation</a>.

  Here is a partial sample:

  <pre>
   [
      {
          "audioLevel": 0,
          "id": "RTCAudioSource_1",
          "kind": "audio",
          "timestamp": 1603448671532842,
          "totalAudioEnergy": 0,
          "totalSamplesDuration": 4.249999999999954,
          "trackIdentifier": "4nP5yeIDzbUm6IJho5jkTps1lnfabsFvTXjH00",
          "type": "media-source"
      },
      {
          "base64Certificate": "MIIBFjCB...QIhAMIfr/NgvhNp16zaoHxGQGrID1STFmBSSSB4V1bxBrTU",
          "fingerprint": "E7:5F:...:FA:5A:1F:A7:E0:55:60",
          "fingerprintAlgorithm": "sha-256",
          "id": "RTCCertificate_E7:5F:E5...F:1D:FA:5A:1F:A7:E0:55:60",
          "timestamp": 1603448671532842,
          "type": "certificate"
      },
      {
          "channels": 1,
          "clockRate": 8000,
          "id": "RTCCodec_audio_Inbound_0",
          "mimeType": "audio/PCMU",
          "payloadType": 0,
          "timestamp": 1603448671532842,
          "type": "codec"
      },
      {
          "channels": 2,
          "clockRate": 48000,
          "id": "RTCCodec_audio_Inbound_111",
          "mimeType": "audio/opus",
          "payloadType": 111,
          "sdpFmtpLine": "minptime=10;useinbandfec=1",
          "timestamp": 1603448671532842,
          "type": "codec"
      },
   ]
   </pre>
 */
@property (strong) NSString* _Nonnull jsonArrayOfReports;
@end

/**
 * Used for sending messages reporting publisher RTC statistics. Set the
 * <[OTPublisherKit rtcStatsReportDelegate]> property to use this delegate.
 * After you call the <[OTPublisherKit getRtcStatsReport]> method,
 * the <[OTPublisherKitRtcStatsReportDelegate publisher:rtcStatsReport:]>
 * message is sent to report the stats.
 */
@protocol OTPublisherKitRtcStatsReportDelegate <NSObject>

@optional

/**
 * Sent when the RTC statistics for the publisher are available, in response
 * to a call to the <[OTPublisherKit rtcStatsReportDelegate]> method.
 *
 * @param publisher The publisher these statistic apply to.
 *
 * @param stats The RTC statistics for the publisher, represented as an
 * array of <OTPublisherRtcStats> objects. For a routed session (a seesion that uses the
 * <a href="https://tokbox.com/developer/guides/create-session/#media-mode">OpenTok
 * Media Router</a>), this array includes one object, defining the statistics
 * for the single video media stream that is sent to the OpenTok Media Router.
 * In a relayed session, the array includes an object for each subscriber
 * to the published stream.
 */
- (void)publisher:(nonnull OTPublisherKit*)publisher
   rtcStatsReport:(nonnull NSArray<OTPublisherRtcStats *> *)stats;

@end

/**
 * Defines a custom transformer for a video stream, to be passed into the
 * <[OTVideoTransformer initWithName:transformer:]> method.
 */
@protocol OTCustomVideoTransformer <NSObject>
/**
 * Called when a video frame is available to be transformed. Transform the
 * data in your implementation of the method.
 * @param frame The frame to be transformed.
 */
- (void)transform:(nonnull OTVideoFrame*)frame;

@end

/**
 * Defines a custom transformer for an audio stream, to be passed into the
 * <[OTAudioTransformer initWithName:transformer:]> method.
 */
@protocol OTCustomAudioTransformer <NSObject>
/**
 * Called when audio data is available to be transformed. Transform the
 * data in your implementation of the method.
 * @param audioData The audio data to be transformed.
 */
- (void)transform:(nonnull OTAudioData*)audioData;

@end

/**
 *  Defines a transformer of a video stream.
 */
@interface OTVideoTransformer : NSObject

/**
* Creates an instance of a Vonage video transformer. For more information,
* see <a href="https://tokbox.com/developer/guides/vonage-media-processor/ios/">Using
* the Vonage Media Processor library</a>. 
* 
* <b>Important:</b> In version 2.27.4+ of the Vonage Video client SDK for iOS,
* you need to add the Vonage Media Library separately from the
* Vonage Video iOS SDK. For details, see
* <a href="https://tokbox.com/developer/guides/vonage-media-processor/ios/#vonage-media-library-integration">Vonage Media Library integration</a>.  
* Check additional information in the Vonage Media Library README.md file.
*
* <b>Note:</b> Media transformers
* are not supported on all devices or iOS versions — see
* <a href="https://tokbox.com/developer/guides/vonage-media-processor/ios/#supported-devices-and-ios-versions">this documentation</a>.
* @param name The name of the Vonage transformer.
* @param properties A JSON string with the properties of the Vonage video transformer.
*/
- (nullable id)initWithName:(nonnull NSString*)name properties:(nonnull NSString *)properties;

/**
* Creates an instance of a custom video transformer.
* @param name The identifier for the transformer.
* @param transformer The transformer.
* @return NULL if an error occurs.
*/
- (nullable id)initWithName:(nonnull NSString*)name transformer:(nonnull id<OTCustomVideoTransformer>)transformer;

@end

/**
 *  Defines a transformer of an audio stream.
 */
@interface OTAudioTransformer : NSObject

/**
* Creates an instance of a Vonage audio transformer. For more information,
* see <a href="https://tokbox.com/developer/guides/vonage-media-processor/ios/">Using
* the Vonage Media Processor library</a>.
*
* <b>Important:</b> In version 2.27.4+ of the Vonage Video client SDK for iOS,
* you need to add the Vonage Media Library separately from the.
* Vonage Video iOS SDK. For details, see
* <a href="https://tokbox.com/developer/guides/vonage-media-processor/ios/#vonage-media-library-integration">Vonage Media Library integration</a>.  
* Check additional information in the Vonage Media Library README.md file.
*
* <b>Note:</b> Media transformers
* are not supported on all devices or iOS versions — see
* <a href="https://tokbox.com/developer/guides/vonage-media-processor/ios/#supported-devices-and-ios-versions">this documentation</a>.
*
* @param name The name of the Vonage transformer.
* @param properties A JSON string with the properties of the Vonage audio transformer.
*/
- (nullable id)initWithName:(nonnull NSString*)name properties:(nonnull NSString *)properties;

/**
* Creates an instance of a custom audio transformer.
* @param name The identifier for the transformer.
* @param transformer The transformer.
* @return NULL if error occurs.
*/
- (nullable id)initWithName:(nonnull NSString*)name transformer:(nonnull id<OTCustomAudioTransformer>)transformer;

@end
