#ifndef asl_wrappers_h
#define asl_wrappers_h

#import <Foundation/Foundation.h>
#import <CoreAudio/CoreAudioTypes.h>
#import <CoreGraphics/CoreGraphics.h>
#import <CoreMedia/CoreMedia.h>

NS_ASSUME_NONNULL_BEGIN

typedef NS_ENUM(int, SessionType) {
    SessionTypeSMOOTHSTREAMING,
    SessionTypeHDS,
    SessionTypeRTMP,
    SessionTypeHLS,
    SessionTypeDASH,
    SessionTypeCFF,
    SessionTypePMP4,
    SessionTypeUNKNOWN
};

typedef NS_ENUM(int, Result) {
    ResultSUCCESS,
    ResultALREADY_INITIALIZED,
    ResultALREADY_DESTROYED,
    ResultINVALID_HANDLE,
    ResultINVALID_ARGUMENTS,
    ResultINVALID_FORMAT,
    ResultINVALID_OBJECT,
    ResultINVALID_CREDENTIALS,
    ResultNOT_AVAILABLE,
    ResultPERMISSION_DENIED,
    ResultOUT_OF_RANGE,
    ResultOUT_OF_MEMORY,
    ResultIO_ERROR,
    ResultIO_EOF,
    ResultINVALID_RESPONSE,
    ResultCOULDNT_CONNECT,
    ResultNOT_INITIALIZED,
    ResultUNSUPPORTED,
    ResultEXPIRED,
    ResultCANCELED,
    ResultDRM_LICENSE_NOT_AVAILABLE,
    ResultBUFFERING,
    ResultFAIL = 0xFFFF
};

typedef NS_ENUM(int, PayloadType) {
    PayloadSAMPLE = 0,
    PayloadSIDECHANNEL = 1,
    PayloadMETADATA = 2,
    PayloadEMPTY = 3,
    PayloadTRANSITION = 4,
    PayloadTRACK_SELECTION = 5
};

typedef NS_ENUM(int, OutputType) {
    OutputTypeAUDIO = 0,
    OutputTypeVIDEO = 1,
    OutputTypeSUBTITLES = 2,
    OutputTypeMETADATA = 3,
    OutputTypeMUXED_AV = 4,
    OutputTypeNONE = 5
};

typedef NS_ENUM(int, PeriodBufferReason) {
    PeriodBufferReasonNEWSTREAM,
    PeriodBufferReasonNEWPERIOD,
    PeriodBufferReasonCROSSPERIODSEEK
};

typedef NS_ENUM(int, SubtitleType) {
    SubtitleTypeWebVTT = 1,
    SubtitleTypeTTML = 2,
    SubtitleTypeSRT = 4
};

typedef NS_ENUM(int, TransitionType) {
    TransitionTypePERIOD,
    TransitionTypeSTREAM
};

typedef NS_ENUM(int, AudioFraming) {
    AudioFramingPLAIN,
    AudioFramingADTS,
    AudioFramingLATM
};

typedef NS_ENUM(int, RequestTag) {
    RequestTagGeneric = 0,
    RequestTagManifest,
    RequestTagResource
};

typedef NS_ENUM(int, MessageType) {
    MessageTypeFatalSegmentDownloadError,
    MessageTypeNoLicense,
    MessageTypeDownloadStatistic,
    MessageTypeAbrStatistics,
    MessageTypePrefetchCompleted,
    MessageTypeTimePrefetchStarted,
    MessageTypeTimePrefetchCompleted,
    MessageTypeRepresentationBlocklisted,
    MessageTypeDownloadError,
    MessageTypeDownloadCanceled,
    MessageTypeOutOfSeekRange,
    MessageTypeNoValidContent,
    MessageTypeCantLoadManifest,
    MessageTypeManifestGap,
    MessageTypeDemuxingError
};


typedef NS_ENUM(int, InitSource) {
    InitSourceManifest,
    InitSourceInitSegment,
    InitSourceMediaSegment
};

@interface PayloadInfo : NSObject
@property (readonly) PayloadType type;
@property (readonly) NSData *data;
@end

@interface TrackSelectionInfo : PayloadInfo
@property (readonly) size_t trackIdx;
@end

@interface TransitionInfo : PayloadInfo
@property (readonly) TransitionType transitionType;
@property (readonly) NSString *id;
@end

@interface SampleInfo : PayloadInfo
@property (readonly) int64_t pts;
@property (readonly) int64_t dts;
@property (readonly) int64_t originPts;
@property (readonly) int64_t duration;
@property (readonly) int64_t timescale;
@property (readonly) BOOL isIFrame;
@property (readonly) BOOL doNotDisplay;
@property (readonly) NSUUID * _Nullable keyId;
@property (readonly) FourCharCode encryptionScheme;
@property (readonly) NSData *IV;
@property (readonly) size_t numSubSamples;
@property (readonly) NSArray<NSNumber*> *numBytesOfClearData;
@property (readonly) NSArray<NSNumber*> *numBytesOfEncryptedData;
@property (readonly) size_t crypt_byte_blocks;
@property (readonly) size_t skip_byte_blocks;
@end

@interface SidechannelInfo : PayloadInfo
@property (readonly) int64_t timescale;
@property (readonly) int64_t originTimescale;
@property (readonly) AudioFormatID audioFormat;
@property (readonly) AudioFraming audioFraming;
@property (readonly) int64_t audioBitrate;
@property (readonly) int audioChannels;
@property (readonly) UInt32 audioSamplingRate;
@property (readonly) UInt32 audioBitsPerSample;
@property (readonly) FourCharCode videoFormat;
@property (readonly) int64_t videoBitrate;
@property (readonly) int videoNalUnitHeaderLength;
@property (readonly) CGSize videoResolution;
@property (readonly) FourCharCode enhancementType;
@property (readonly) NSData *enhancementData;
@end

@interface TrackInfo : NSObject
@property (readonly) NSString* title;
@property (readonly) NSString* language;
@property (readonly) NSDictionary<NSString*,NSArray<NSString*>*> *roles;
@end

@interface QualityInfo : NSObject
@property (readonly) NSString* format;
@property (readonly) NSString* codecData;
@property (readonly) int64_t bitrate;
@end

@interface VideoQualityInfo : QualityInfo
@property (readonly) UInt32 width;
@property (readonly) UInt32 height;
@property (readonly) float fps;
@end

@interface AudioQualityInfo : QualityInfo
@property (readonly) UInt32 samplingRate;
@property (readonly) int channels;
@property (readonly) int bitsPerSample;
@end

@interface AudioTrackInfo : TrackInfo
@property (readonly) NSArray<AudioQualityInfo*> *qualities;
@end

@interface VideoTrackInfo : TrackInfo
@property (readonly) BOOL isTrickPlay;
@property (readonly) NSArray<VideoQualityInfo*> *qualities;
@end

@interface SubtitleTrackInfo : TrackInfo
@property (readonly) SubtitleType type;
@property (readonly) BOOL isForced;
@end

@interface SubtitleSegment : NSObject
@property (readonly) int64_t startUs;
@property (readonly) int64_t durationUs;
@property (readonly) int64_t offsetUs;
@property (readonly) NSString* content;
@property (readonly) NSString* imageBaseUrl;
@property (readonly) NSArray<NSData*> *resources;
@end

@interface SubtitleSegmentFuture : NSObject
- (nullable SubtitleSegment*) get;
@end

@interface PeriodInfo : NSObject
@property (readonly) NSString *periodId;
@property (readonly) NSArray<VideoTrackInfo*> *videoTracks;
@property (readonly) NSArray<AudioTrackInfo*> *audioTracks;
@property (readonly) NSArray<SubtitleTrackInfo*> *subtitleTracks;
@end

@interface DownloadErrorMessage : NSObject
@property (readonly) NSURL *url;
@property (readonly) RequestTag requestType;
@property (readonly) UInt32 httpStatus;
@property (readonly) NSString *errorMessage;
@property (readonly) BOOL isFatal;
@end

@interface AbrStatMessage : NSObject
@property (readonly) int64_t inputBandwidth;
@property (readonly) bool usingDefaultBandwidth;
@property (readonly) double fullness;
@property (readonly) int64_t chosenBitrate;
@property (readonly) NSString *reason;
@property (readonly) OutputType track;
@end

@interface PSSHEntry : NSObject
@property (readonly) NSUUID *uuid;
@property (readonly) NSData *box;
@end

@interface ProtectionEntry : NSObject
@property (readonly) NSString *schemeIdUri;
@property (readonly) NSString *value;
@property (readonly) NSDictionary<NSString*,NSString*> *properties;
@end

@protocol DrmInterface
- (Result) initWithPSSHBoxes:(NSArray<PSSHEntry*>*)boxes;
- (Boolean) initCommonEncryption:(InitSource)source withScheme:(NSString*)scheme withId:(NSString*)identifier;
- (Boolean) updateCommonEncryption:(InitSource)source  withId:(NSString*)identifier entries:(NSArray<ProtectionEntry*>*)entries;
@end

@interface AdaptationAlgorithmConfig : NSObject
@property int64_t minDurationQualityIncreaseMs;
@property int64_t maxDurationQualityDecreaseMs;
@property double bufferDegradationPenalty;
@property double bufferDegradationRecovery;
@property int64_t bufferDegradationSampleSize;
@end

@interface BandwidthMeterConfig : NSObject
@property int64_t minSampledBytes;
@property int64_t defaultBitrateEstimate;
@property double estimateFraction;
@property int32_t percentileWeight;
@property double percentile;
@property double alpha;
@property double halfLifeSlow;
@property double halfLifeFast;
@end

@interface PeriodCallbacks : NSObject
- (Result) selectVideoTrack:(int) index;
- (Result) selectAudioTrack:(int) index;
- (Result) selectVideoRepresentation:(int) index;
@end

typedef void (^PeriodAboutToBuffer)(PeriodBufferReason, PeriodInfo *, PeriodCallbacks *);
typedef void (^OnMessageCallback)(NSObject *, MessageType);
typedef BOOL (^RepresentationFilter)(QualityInfo *);

@interface VTSession : NSObject
@property (readonly) BOOL isOpen;
@property (readonly) BOOL isOpening;
@property (readonly) BOOL isLive;
@property (readonly) BOOL isBuffering;
@property (readonly) BOOL isEndOfStream;

@property (readonly) int64_t durationUs;
@property (readonly) CMTimeRange seekWindow;
@property (readonly) NSArray<AudioTrackInfo*> *audioTracks;
@property UInt32 selectedAudioTrack;
@property (readonly) NSArray<VideoTrackInfo*> *videoTracks;
@property UInt32 selectedVideoTrack;
@property (readonly) NSArray<SubtitleTrackInfo*> *subtitleTracks;

@property CGSize maxVideoResolution;
@property int64_t maxBitrate;
@property int64_t initialBandwidthEstimate;
@property double minPrebufferTime;
@property double maxPrebufferTime;
@property double minRebufferTime;
@property double liveEdgeDelay;
@property int64_t requestConnectTimeoutMs;
@property int64_t manifestConnectTimeoutMs;
@property int64_t segmentConnectTimeoutMs;
@property int64_t requestReadTimeoutMs;
@property int64_t manifestReadTimeoutMs;
@property int64_t segmentReadTimeoutMs;
@property int maxRequestAttempts;
@property int maxManifestAttempts;
@property int maxSegmentAttempts;
@property int64_t requestRetryBaseDelayMs;
@property int64_t manifestRetryBaseDelayMs;
@property int64_t segmentRetryBaseDelayMs;
@property double requestRetryBackoffFactor;
@property double requestRetryFuzzFactor;
@property int64_t requestRetryMaxDelayMs;
@property NSString* proxy;
@property int selectedVideoRendition;
@property int selectedAudioRendition;
@property AdaptationAlgorithmConfig* adaptationAlgorithmConfig;
@property BandwidthMeterConfig* bandwidthMeterConfig;

- (instancetype)init;
- (instancetype)initWithMaxConnectionAge:(UInt32)maxAge manualAdaptationMode:(Boolean) mode representationFallback:(Boolean) enabled;

- (void) setOnNextPeriodAboutToBuffer:(PeriodAboutToBuffer) callback;
- (void) setOnMessageCallback:(OnMessageCallback) callback;
- (void) setRepresentationFilter:(RepresentationFilter) filter;
- (void) setDrmInterface:(id<DrmInterface>) drm;
- (Result) open:(NSURL*) url withType: (SessionType) type andStartTime: (double)startTime;
- (Result) close;
- (Result) peek:(OutputType) outputType onPayload:(PayloadInfo* _Nullable * _Nonnull) outInfo atIndex:(int) index;
- (Result) read:(OutputType) outputType onPayload:(PayloadInfo* _Nullable * _Nonnull) outInfo;
- (Result) seek:(CMTime) time;
- (BOOL)isAdaptationModeManual;
- (BOOL) hasComponent: (OutputType) type;
- (BOOL) isBufferingType: (OutputType) type;
- (BOOL) isEndOfStreamType: (OutputType) type;
- (SubtitleSegmentFuture*) downloadSubtitleSegmentForTrackIdx:(size_t)trackIdx atPositionUs:(int64_t) positionUs;
@end

NS_ASSUME_NONNULL_END

#endif // asl_wrappers_h
