//
//  OTNetworkStatsKit.h
//  otkit-objc-libs
//
//  Created by Charley Robinson on 12/1/14.
//
//

#import <Foundation/Foundation.h>
#import <OpenTok/OTVideoEventReason.h>

/**
 * Estimated network condition score for a transport.
 *
 * This enum represents the overall health of the network connection for
 * a given transport (local or remote). It is typically derived from metrics
 * such as packet loss and estimated available bandwidth.
 * Higher values indicate better network conditions.
 *
 * OTNetworkConditionWarning and OTNetworkConditionCritical indicate
 * degraded network conditions that may trigger audio fallback callbacks.
 * If audio fallback is enabled, the SDK will notify via the corresponding
 * callbacks, and in the critical state, video may be disabled to preserve
 * call stability.
 */
typedef NS_ENUM(int32_t, OTNetworkCondition) {
    /**
     * Network condition could not be determined.
     */
    OTNetworkConditionUnknown = 0,

    /**
     * Severe network issues.
     *
     * Audio fallback is triggered if enabled.
     */
    OTNetworkConditionCritical = 1,

    /**
     * Poor network conditions.
     *
     * Video quality is heavily impacted, and a video disable warning
     * is triggered if audio fallback is enabled.
     */
    OTNetworkConditionWarning = 2,

    /**
     * Moderate network conditions.
     *
     * Video quality may be restricted by the sender.
     */
    OTNetworkConditionFair = 3,

    /**
     * Good network conditions.
     *
     * Minor or temporary issues may occur.
     */
    OTNetworkConditionGood = 4,

    /**
     * Excellent network conditions.
     *
     * Video quality is optimal, and the estimated available bandwidth
     * can accommodate the maximum bitrate for the current resolution.
     */
    OTNetworkConditionExcellent = 5
};

/**
 * Indicates the source of video or network degradation in the session.
 *
 * This enum identifies which side of the call is responsible for observed
 * network issues impacting video quality. It complements per-transport
 * network condition metrics.
 */
typedef NS_ENUM(int32_t, OTNetworkDegradationSource) {

    /**
     * No network degradation detected.
     */
    OTNetworkDegradationSourceNone = 0,

    /**
     * The source of network degradation cannot be determined.
     */
    OTNetworkDegradationSourceBothOrUnclear = 1,

    /**
     * The local participant’s network is the primary cause
     * of the observed degradation.
     */
    OTNetworkDegradationSourceLocal = 2,

    /**
     * The remote participant’s network is the primary cause
     * of the observed degradation.
     */
    OTNetworkDegradationSourceRemote = 3
};

/**
 * Provides network-level transport statistics.
 *
 * The `OTTransportStats` class exposes metrics related to the underlying
 * network transport layer of a WebRTC connection. These stats reflect
 * current conditions such as the estimated available bandwidth and can be
 * used for monitoring or debugging network performance issues.
 */
@interface OTTransportStats : NSObject

/**
 * The estimated available connection bandwidth, in bits per second (bps).
 */
@property (readonly) int64_t connectionEstimatedBandwidth;

/**
 * The current network condition score.
 *
 * This value represents an assessment of the local participant’s
 * network quality based on transport-level metrics.
 */
@property (readonly) OTNetworkCondition networkCondition;

/**
 * The primary reason impacting the current network condition.
 *
 * This value indicates the dominant factor influencing the
 * network condition score, such as bandwidth limitations,
 * packet loss, or other network-related causes.
 */
@property (readonly) OTNetworkReason networkConditionReason;

- (nonnull instancetype)initWithConnectionEstimatedBandwidth:(int64_t)connectionEstimatedBandwidth
                                            networkCondition:(OTNetworkCondition)networkCondition
                                     networkConditionReason:(OTNetworkReason)networkConditionReason;

@end


/**
 * Represents video statistics reported by the sender side, such as bitrate estimates.
 */
@interface OTSenderStats : NSObject

/**
 * The maximum bitrate that can be estimated for the sender connection, in bps (bits
 * per second).
 */
@property (readonly) int64_t connectionMaxAllocatedBitrate;

/**
 * The current bandwidth estimation for the sender connection, in bps (bits per
 * second).
 */
@property (readonly) int64_t connectionEstimatedBandwidth;

- (nonnull instancetype)initWithconnectionMaxAllocatedBitrate:(int64_t)connectionMaxAllocatedBitrate
                                 connectionEstimatedBandwidth:(int64_t)connectionEstimatedBandwidth;

@end

/**
 * Describes video statistics for a subscriber. See
 * <[OTSubscriberKit setNetworkStatsDelegate:]>.
 */
@interface OTSubscriberKitVideoNetworkStats : NSObject

/**
 * The estimated number of video packets lost by this subscriber.
 */
@property (readonly) uint64_t videoPacketsLost;

/**
 * The number of video packets received by this subscriber.
 */
@property (readonly) uint64_t videoPacketsReceived;

/**
 * The number of video bytes received by this subscriber.
 */
@property (readonly) uint64_t videoBytesReceived;

/**
 * The timestamp, in milliseconds since the Unix epoch, for when these stats
 * were gathered.
 */
@property (readonly) double timestamp;

/**
 * Sender-side network estimation stats.
 * This property is optional and may be nil if data is not available.
 * Due to network latency, sender statistics may not be
 * immediately available after the initial stats request.
 *
 * @deprecated Use subscriber media link stats (OTSubscriberKitMediaLinkStats)
 * instead for complete network metrics including remote publisher transport
 * and network degradation source information.
 */
@property (readonly, nullable) OTSenderStats *senderStats __attribute__((deprecated("Use subscriber media link stats (OTSubscriberKitMediaLinkStats) instead")));

/**
 * The width of the video frame, in pixels.
 */
@property (readonly) int32_t width;

/**
 * The height of the video frame, in pixels.
 */
@property (readonly) int32_t height;

/**
 * The decoded frame rate (in frames per second).
 */
@property (readonly) double decodedFrameRate;

/**
 *The bitrate, in bits per second.
 */
@property (readonly) int64_t bitrate;

/**
 * The total bitrate, including RTP headers, padding, and payload,
 * in bits per second.
 */
@property (readonly) int64_t totalBitrate;

/**
 * The number of times the subscriber’s video playback has paused.
 *
 * Video is considered paused if the time elapsed since the last rendered frame
 * exceeds 5 seconds.
 */
@property (readonly) int64_t pauseCount;

/**
 * The cumulative duration (in milliseconds) of all video pauses.
 */
@property (readonly) int64_t totalPausesDuration;

/**
 * The number of times the subscriber’s video has frozen.
 *
 * A freeze is defined according to
 * https://www.w3.org/TR/webrtc-stats/#dom-rtcinboundrtpstreamstats-freezecount
 */
@property (readonly) int64_t freezeCount;

/**
 * The cumulative duration (in milliseconds) of all video freezes.
 */
@property (readonly) int64_t totalFreezesDuration;

/**
 * The codec currently used for this subscriber.
 */
@property (readonly, nullable) NSString *codec;


- (nonnull instancetype)initWithPacketsLost:(uint64_t)packetsLost
                            packetsReceived:(uint64_t)packetsReceived
                              bytesReceived:(uint64_t)bytesReceived
                                  timestamp:(double)timestamp;

- (nonnull instancetype)initWithPacketsLost:(uint64_t)packetsLost
                            packetsReceived:(uint64_t)packetsReceived
                              bytesReceived:(uint64_t)bytesReceived
                                  timestamp:(double)timestamp
                                senderStats:(OTSenderStats * _Nullable)senderStats;

- (nonnull instancetype)initWithPacketsLost:(uint64_t)packetsLost
                            packetsReceived:(uint64_t)packetsReceived
                              bytesReceived:(uint64_t)bytesReceived
                                  timestamp:(double)timestamp
                                senderStats:(OTSenderStats * _Nullable)senderStats
                                      width:(int32_t)width
                                     height:(int32_t)height
                           decodedFrameRate:(double)decodedFrameRate
                                    bitrate:(int64_t)bitrate
                               totalBitrate:(int64_t)totalBitrate
                                 pauseCount:(int64_t)pauseCount
                        totalPausesDuration:(int64_t)totalPausesDuration
                                freezeCount:(int64_t)freezeCount
                       totalFreezesDuration:(int64_t)totalFreezesDuration
                                      codec:(NSString * _Nullable)codec;
@end


/**
 * Provides subscriber media link statistics including local and remote
 * transport metrics and network degradation information.
 *
 * Since audio and video share the same underlying transport, this class
 * consolidates the local transport, remote publisher transport, and
 * network degradation source into a single object.
 */
@interface OTSubscriberKitMediaLinkStats : NSObject

/**
 * Local transport and network statistics for this subscriber.
 *
 * This property reflects transport-level metrics for the subscriber's
 * local connection. Some fields may be limited if sender-side statistics
 * and/or audio fallback are disabled.
 */
@property (readonly, nonnull) OTTransportStats *transport;

/**
 * Remote publisher transport and network statistics.
 *
 * This property reflects transport-level metrics for the remote publisher.
 * Some fields may be limited if sender-side statistics and/or audio fallback
 * are disabled.
 */
@property (readonly, nonnull) OTTransportStats *remotePublisherTransport;

/**
 * Indicates the source of network degradation, if any.
 *
 * This value identifies whether network degradation is primarily caused
 * by the local subscriber, the remote publisher, or cannot be determined.
 * Availability may be limited if sender-side statistics and/or audio
 * fallback are disabled.
 */
@property (readonly) OTNetworkDegradationSource networkDegradationSource;

- (nonnull instancetype)initWithTransport:(OTTransportStats * _Nonnull)transport
              remotePublisherTransport:(OTTransportStats * _Nonnull)remotePublisherTransport
                   networkDegradationSource:(OTNetworkDegradationSource)networkDegradationSource;

@end


/**
 * Describes audio statistics for a subscriber. See
 * <[OTSubscriberKit setNetworkStatsDelegate:]>.
 */
@interface OTSubscriberKitAudioNetworkStats : NSObject

/**
 * The estimated number of audio packets lost by this subscriber.
 */
@property (readonly) uint64_t audioPacketsLost;

/**
 * The number of audio packets received by this subscriber.
 */
@property (readonly) uint64_t audioPacketsReceived;

/**
 * The number of audio bytes received by this subscriber.
 */
@property (readonly) uint64_t audioBytesReceived;

/**
 * The timestamp, in milliseconds since the Unix epoch, for when these stats
 * were gathered.
 */
@property (readonly) double timestamp;

/**
 * Sender-side network estimation stats.
 * This property is optional and may be nil if data is not available.
 *
 * @deprecated Use subscriber media link stats (OTSubscriberKitMediaLinkStats)
 * instead for complete network metrics including remote publisher transport
 * and network degradation source information.
 */
@property (readonly, nullable) OTSenderStats *senderStats __attribute__((deprecated("Use subscriber media link stats (OTSubscriberKitMediaLinkStats) instead")));

- (nonnull instancetype)initWithPacketsLost:(uint64_t)packetsLost
                            packetsReceived:(uint64_t)packetsReceived
                              bytesReceived:(uint64_t)bytesReceived
                                  timestamp:(double)timestamp;

- (nonnull instancetype)initWithPacketsLost:(uint64_t)packetsLost
                            packetsReceived:(uint64_t)packetsReceived
                              bytesReceived:(uint64_t)bytesReceived
                                  timestamp:(double)timestamp
                                senderStats:(OTSenderStats * _Nullable)senderStats;
@end

/**
 * Provides publisher media link statistics including local
 * transport metrics.
 *
 * Since video and audio share the same underlying transport, this class
 * consolidates the local transport statistics into a single object.
 */
@interface OTPublisherKitMediaLinkStats : NSObject

/**
 * The connection ID of the client subscribing to the stream.
 */
@property (nonnull, readonly) NSString* connectionId;

/**
 * The subscriber ID of the client subscribing to the stream
 * (in a relayed session). In a routed session, this is set to
 * an empty string.
 */
@property (nonnull, readonly) NSString* subscriberId;

/**
 * Transport-level statistics for the publisher's connection.
 */
@property (readonly, nonnull) OTTransportStats *transport;

- (nonnull instancetype)initWithConnectionId:(NSString * _Nonnull)connectionId
                                subscriberId:(NSString * _Nonnull)subscriberId
                                   transport:(OTTransportStats * _Nonnull)transport;

@end


/**
 * Describes statistics for a single published video layer.
 *
 * In a simulcast configuration, each entry corresponds to one independent
 * video encoding (for example, low-, medium-, and high-resolution streams
 * sent in parallel). For SVC (Scalable Video Coding), the publisher typically
 * sends a single video encoding, with scalability (temporal, spatial, or both)
 * internally encoded and described via the `scalabilityMode` property.
 */
@interface OTPublisherKitVideoLayerStats : NSObject

/** The width of the video frame, in pixels. */
@property (readonly) int32_t width;

/** The height of the video frame, in pixels. */
@property (readonly) int32_t height;

/** The encoded video frame rate (in frames per second). */
@property (readonly) double encodedFrameRate;

/** The bitrate of this video layer, in bits per second. */
@property (readonly) int64_t bitrate;

/**
 * The total bitrate, including RTP headers, padding, and payload,
 * in bits per second.
 */
@property (readonly) int64_t totalBitrate;

/**
 * The scalability mode string (for example, "L1T1", "L3T3") describing
 * the spatial and/or temporal scalability of this video layer.
 * This property can be null or an empty string when it is not available.\
 */
@property (nullable, readonly) NSString* scalabilityMode;

/**
 * The reason for any quality limitation experienced by this video layer.
 */
@property (readonly) OTPublisherVideoEventReason qualityLimitationReason;

/**
 * The codec currently used for this video layer.
 */
@property (nullable, readonly) NSString* codec;

- (nonnull instancetype)initWithWidth:(int32_t)width
                               height:(int32_t)height
                     encodedFrameRate:(double)encodedFrameRate
                              bitrate:(int64_t)bitrate
                         totalBitrate:(int64_t)totalBitrate
                      scalabilityMode:(NSString* _Nullable)scalabilityMode
              qualityLimitationReason:(OTPublisherVideoEventReason)qualityLimitationReason
                                codec:(NSString* _Nullable)codec;

@end


/**
 * Describes video statistics for a publisher. See
 * <[OTPublisherKit setNetworkStatsDelegate:]>.
 */
@interface OTPublisherKitVideoNetworkStats : NSObject

/**
 * The connection ID of the client subscribing to the stream.
 */
@property (nonnull, readonly) NSString* connectionId;

/**
 * The subscriber ID of the client subscribing to the stream
 * (in a relayed session). In a routed session, this is set to
 * an empty string.
 */
@property (nonnull, readonly) NSString* subscriberId;

/**
 * The estimated number of video packets that did not reach the subscriber
 * (or the OpenTok Media Router).
 */
@property (readonly) int64_t videoPacketsLost;

/**
 * The number of video packets packets sent to the subscriber
 * (or to the OpenTok Media Router).
 */
@property (readonly) int64_t videoPacketsSent;

/**
 * The number of video bytes sent to the subscriber (or to
 * the OpenTok Media Router).
 */
@property (readonly) int64_t videoBytesSent;

/**
 * The timestamp, in milliseconds since the Unix epoch, for when these stats
 * were gathered.
 */
@property (readonly) double timestamp;


/**
 * The array of video layer statistics (instances of
 * <OTPublisherKitVideoLayerStats>).
 */
@property (nonnull, readonly) NSArray<OTPublisherKitVideoLayerStats*>* videoLayers;

/**
 * Network estimation stats.
 */
@property (readonly, nullable) OTTransportStats *transport;

/**
 * The timestamp, in milliseconds since the Unix epoch, from which 
 * the cumulative totals started accumulating.
 */
@property (readonly) double startTime;

- (nonnull instancetype)initWithConnectionId:(NSString* _Nonnull)connectionId
                                 subscriberId:(NSString* _Nonnull)subscriberId
                           packetsLost:(int64_t)packetsLost
                           packetsSent:(int64_t)packetsSent
                             bytesSent:(int64_t)bytesSent
                             timestamp:(double)timestamp
                             startTime:(double)startTime
                           videoLayers:(NSArray<OTPublisherKitVideoLayerStats*>* _Nonnull)videoLayers
                            transport:(OTTransportStats * _Nullable)transport;
@end


/**
 * Describes audio statistics for a publisher. See
 * <[OTPublisherKit setNetworkStatsDelegate:]>.
 */
@interface OTPublisherKitAudioNetworkStats : NSObject

/**
 * The connection ID of the subscribing client.
 */
@property (nonnull, readonly) NSString* connectionId;

/**
 * The subscriber ID of the client subscribing to the stream
 * (in a relayed session). In a routed session, this is set to
 * an empty string.
 */
@property (nonnull, readonly) NSString* subscriberId;

/**
 * The estimated number of audio packets that did not reach the subscriber
 * (or the OpenTok Media Router).
 */
@property (readonly) int64_t audioPacketsLost;

/**
 * The number of audio packets sent to the subscriber (or to
 * the OpenTok Media Router).
 */
@property (readonly) int64_t audioPacketsSent;

/**
 * The number of audio bytes sent to the subscriber (or to
 * the OpenTok Media Router)
 */
@property (readonly) int64_t audioBytesSent;

/**
 * The timestamp, in milliseconds since the Unix epoch, for when these stats
 * were gathered.
 */
@property (readonly) double timestamp;

/**
 * The timestamp, in milliseconds since the Unix epoch, from which 
 * the cumulative totals started accumulating.
 */
@property (readonly) double startTime;

/**
 * Network estimation stats.
 */
@property (readonly, nullable) OTTransportStats *transport;

- (nonnull instancetype)initWithConnectionId:(NSString* _Nonnull)connectionId
                                 subscriberId:(NSString* _Nonnull)subscriberId
                           packetsLost:(int64_t)packetsLost
                           packetsSent:(int64_t)packetsSent
                             bytesSent:(int64_t)bytesSent
                             timestamp:(double)timestamp
                             startTime:(double)startTime
                             transport:(OTTransportStats* _Nullable) transport;

@end
