//
//  CLDownloadStats.h
//  mpl
//
//  Created by Emil Pettersson on 10/04/16.
//  Copyright © 2016 Castlabs GmbH. All rights reserved.
//

#import <Foundation/Foundation.h>

#pragma mark - Errors

FOUNDATION_EXPORT const NSErrorDomain CLDownloadHTTPErrorDomain; // @"CLDownloadHTTPErrorDomain"

FOUNDATION_EXPORT const NSErrorDomain CLDownloadErrorDomain; // @"CLDownloadErrorDomain"

FOUNDATION_EXPORT const NSInteger CLQualityDownloadError; // 1001
FOUNDATION_EXPORT const NSInteger CLSetDownloadError; // 1002

#pragma mark - CLDownloadStatus

/**
 * Represents the status of a download.
 */
typedef NS_ENUM(NSUInteger, CLDownloadStatus) {
    /** Download is idle */
    CLDownloadIdle = 0,
    /** Download is paused */
    CLDownloadPaused,
    /** Download is running (transitions to Idle when completed) */
    CLDownloadRunning,
};

#pragma mark - CLDownloadSize

/**
 * Represents size of a download, either precise or estimated.
 */
struct CLDownloadSize {
    /** Size value in bytes (or CLDownloadSizeUnknownValue if not known). */
    int64_t value;
    /** Indicates if the size is precise or estimated. */
    BOOL estimated;
};

typedef struct CLDownloadSize CLDownloadSize;

FOUNDATION_EXPORT const int64_t CLDownloadSizeUnknownValue; // -1LL
FOUNDATION_EXPORT const CLDownloadSize CLDownloadSizeUnknown; // {CLDownloadSizeUnknownValue, YES}
FOUNDATION_EXPORT const CLDownloadSize CLDownloadSizeZero; // {0LL, NO}

static inline CLDownloadSize CLMakeDownloadSize(int64_t value, BOOL estimated) {
    CLDownloadSize size = {value, estimated};
    return size;
}

static inline BOOL CLDownloadSizeIsUnknown(CLDownloadSize size) {
    return (CLDownloadSizeUnknownValue == size.value);
}

static inline BOOL CLDownloadSizeIsEqual(CLDownloadSize first, CLDownloadSize second) {
    return (first.value == second.value && first.estimated == second.estimated);
}

#pragma mark - CLDownloadProgress

/**
 * Represents progression of a download, either precise or estimated.
 *
 * value:
 *   Progress value in 0.0-1.0 scaled percentage (or CLDownloadProgressUnknownValue if not known).
 *
 * estimated:
 *   Indicates if the progress is estimated or precise.
 */
struct CLDownloadProgress {
    float value;    // Progress value (0.0-1.0)
    BOOL estimated; // Estimated flag
};

typedef struct CLDownloadProgress CLDownloadProgress;

FOUNDATION_EXPORT const float CLDownloadProgressUnknownValue; // -1.0f
FOUNDATION_EXPORT const CLDownloadProgress CLDownloadProgressUnknown; // {CLDownloadProgressUnknownValue, YES}
FOUNDATION_EXPORT const CLDownloadProgress CLDownloadProgressZero; // {0.0f, NO}

static inline CLDownloadProgress CLMakeDownloadProgress(float value, BOOL estimated) {
    CLDownloadProgress progress = {value, estimated};
    return progress;
}

static inline BOOL CLDownloadProgressIsUnknown(CLDownloadProgress progress) {
    return (CLDownloadProgressUnknownValue == progress.value);
}

static inline CLDownloadProgress CLDownloadProgressCompute(int64_t numer, CLDownloadSize denom) {
    if (0 < denom.value) {
        return CLMakeDownloadProgress(numer / (double)denom.value, denom.estimated);
    }
    return CLDownloadProgressUnknown;
}

#pragma mark - CLDownloadStats

@protocol CLDownloadStats <NSObject>

/**
 * Size value in bytes, either precise or estimated (see CLDownloadSize).
 */
@property (readonly) CLDownloadSize expectedBytes;

/**
 * Number of bytes downloaded
 */
@property (readonly) int64_t downloadedBytes;

/**
 * Progress in 0.0-1.0 scaled percentage, either precise or estimated (see CLDownloadProgress).
 */
@property (readonly) CLDownloadProgress progress;

@end
