//
//  CODownloadManager.m
//  classonline
//
//  Created by hyz on 2019/2/25.
//  Copyright © 2019 offcn. All rights reserved.
//

#import "CODownloadManager.h"
#import "SyncDownloadHandler.h"
#import "WXCOUtility.h"
//#import "CODownloadObject.h"
//#import "COPlaybackDownloadManager.h"
//#import "CODownloadManager+NWN.h"

@interface CODownloadManager ()

/// 下载通道可以同时执行的下载的最大下载并发数量
@property (nonatomic, assign, readwrite) NSInteger maxDownloadCount;
/// 下载完成的下载模型数据集合
@property (nonatomic, strong) NSMutableArray <CODownloadModel *> *completeDownloads;
/// 网络变化时缓存的下载对象
@property (nonatomic, strong) NSMutableArray <CODownloadObject *> *networkChangeCacheDownloads;
/// 上次由于app退出时缓存的下载对象 */
@property (nonatomic, strong) NSMutableArray <CODownloadObject *> *lastAppTerminateDownloads;
/// 下载记录同步处理器
@property (nonatomic, strong) SyncDownloadHandler *syncDownloadHandler;

@end

@implementation CODownloadManager

#pragma mark - Init

static CODownloadManager *instance=nil;
+ (instancetype)sharedInstance {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken,^{
        if(!instance){
            instance = [[super allocWithZone:NULL] init];
        }
    });
    return instance;
}

- (instancetype)init {
    if (self = [super init]) {
        self.maxDownloadCount = 3; // 默认并发下载数量
//        [[COPlaybackDownloadManager sharedInstance] setOffcnLiveDownloadMaxQueueCount:self.maxDownloadCount];
//        [self registerNWNDownloadNotification];
    }
    
    return self;
}

#pragma mark - Public Methods

- (void)co_resetDownloadInfoWithUserID:(NSString *)userID {
    // 如果本地已经有数据，则不执行本方法；本操作仅限于启动后一次性从数据库里读取数据
    if (self.allDownloads.count > 0) {
        return;
    }
    
    [self cleanDownloadArrayData];
    
    NSMutableArray <CODownloadModel *> *downloadModelArr = [CODownloadModel getUserAllDownloadDataWithUserID:userID];
    for (CODownloadModel *model in downloadModelArr) {
        CODownloadObject *downloadObject = [[CODownloadObject alloc] initWithDownloadObject:model];
        [self.allDownloads addObject:downloadObject];
        if (downloadObject.downloadModel.down_state != stateCompleted &&
            downloadObject.downloadModel.current_size >= downloadObject.downloadModel.total_size) {
            downloadObject.downloadModel.down_state = stateCompleted;
        }
        // 将未完成的下载放进下载队列
        if ([self co_isDownloadCompleted:downloadObject] == NO) {
            if (downloadObject.downloadModel.down_state == stateCompleted) { // 文件丢失
                downloadObject.downloadModel.down_state = stateInterupt;
                [downloadObject.downloadModel updateModel2Database];
            }
            [self.downloadingQueue addObject:downloadObject];
        } else {
            [self.completeDownloads addObject:model];
        }
    }
    [self co_resetAllDownloadStatus];
    [self co_restartDownloadByAppTerminate];
}

- (void)co_emptyAllDownloadDataWithUserID:(NSString *)userID {
    for (CODownloadObject *object in self.allDownloads) {
        [object downloadRemoveWithUserID:userID];
    }
    
    [self cleanDownloadArrayData];
}

- (void)co_logoutPauseAllDownloadData {
    for (CODownloadObject *object in self.downloadingQueue) {
        if (object.downloadModel.down_state == stateDownloading || object.downloadModel.down_state == stateWaiting) {
            [object downloadPause:NO withChangeDownloadState:NO];
        }
    }
    
    [self cleanDownloadArrayData];
}

- (void)co_restartDownloadByAppTerminate {
    if (self.lastAppTerminateDownloads.count <= 0) {
        return; // 没有发现可以恢复的下载
    }
    
    if (self.isReachable == YES) {
        if (self.isViaWWAN == YES) { // 在移动网络环境下将要执行下载操作
            __weak typeof(self) weakSelf = self;
            [self co_willDownloadInWWANNetwork:self.lastAppTerminateDownloads cancelBlock:^(BOOL cancel) {
                weakSelf.lastAppTerminateDownloads = nil;
            }];
        } else { // 在WI-FI网络环境下将要执行下载操作
            [self co_willDownloadInWIFINetwork:self.lastAppTerminateDownloads];
            self.lastAppTerminateDownloads = nil;
        }
    } else {  // 在无网络环境下，先将这些数据放入networkChangeCacheDownloads数组中，等待网络可用时，继续下载
        for (CODownloadObject *object in self.lastAppTerminateDownloads) {
            [self.networkChangeCacheDownloads addObject:object];
        }
        self.lastAppTerminateDownloads = nil;
    }
}

- (void)co_networkChanged:(NetworkStatus)network {
    if (network == ReachableViaWWAN) { // 如果当前是移动网络，先检查下载通道中是否有下载对象
        for (CODownloadObject *object in self.downloadingQueue) {
            if (object.downloadModel.down_state == stateDownloading || object.downloadModel.down_state == stateWaiting) {
                [object downloadPause:NO];
                [self.networkChangeCacheDownloads addObject:object];
            }
        }
        
        if (self.networkChangeCacheDownloads.count > 0) { // 如果下载通道中存在下载对象，提示用户将要消耗流量
            __weak typeof(self) weakSelf = self;
            [self co_willDownloadInWWANNetwork:self.networkChangeCacheDownloads cancelBlock:^(BOOL cancel) {
                weakSelf.networkChangeCacheDownloads = nil; // 不管是否是同意使用流量，数组都要清空
            }];
        }
    }
    else if (network == NotReachable) { // 如果当前是无网络，将下载通道中的下载对象记录下，等到网络可用时，方便再次开启下载
        for (CODownloadObject *object in self.downloadingQueue) {
            if (object.downloadModel.down_state == stateDownloading || object.downloadModel.down_state == stateWaiting) {
                [object downloadPause:NO];
                [self.networkChangeCacheDownloads addObject:object];
            }
        }
    }
    else if (network == ReachableViaWiFi) { // 如果是WI-FI网络，检测数组是否有可恢复的下载对象
        if (self.networkChangeCacheDownloads.count > 0) {
            [self co_willDownloadInWIFINetwork:self.networkChangeCacheDownloads];
        }
        self.networkChangeCacheDownloads = nil;
    }
}

- (void)co_startDownload:(NSMutableArray <CODownloadObject *>*)objectArray
     downloadRejectBlock:(nullable void (^)(NSMutableArray<CODownloadRejectModel *> * _Nullable))block
   subjoinRejectionArray:(nullable NSMutableArray *)rejectArray
    withPriorityDownload:(BOOL)isPriority {
    if (objectArray == nil || objectArray.count <= 0) { // 没发现可以下载的对象
        if (WXCOIsNilOrNull(block) == NO) { // 抛出被拒回调数据
            if (rejectArray == nil) {
                rejectArray = [NSMutableArray array];
                CODownloadRejectModel *model = [[CODownloadRejectModel alloc] init];
                model.reason = DownloadRejectReasonEmptyList;
                [rejectArray addObject:model]; // 放在首位，由于提前判断被拒条件
            }
        
            block(rejectArray); // 没有发现可下载的数据
        }
        return;
    }
    
    if (self.isReachable == NO) { // 如果处于无网络环境下
        if (WXCOIsNilOrNull(block) == NO) {
            if (rejectArray == nil) {
                rejectArray = [NSMutableArray array];
            }
            CODownloadRejectModel *model = [[CODownloadRejectModel alloc] init];
            model.reason = DownloadRejectReasonNoNetwork;
            [rejectArray insertObject:model atIndex:0]; // 放在首位，由于提前判断被拒条件
            block(rejectArray); // 无网络环境下不能开始下载
        }
        return;
    }
    
    // 第一步：objectArray 对象中有正在下载的，保留该下载对象
    // 第二步：
    //      1、优先下载时：先暂停被objectArray数组挤掉（如果objectArray使用不了那么多的通道，有可能不会被暂停）的正在下载对象，然后让objectArray中的数据进入下载器通道
    //      2、普通下载时：则将objectArray数据追加到downloadingQueue队列中，按照downloadingQueue数组中的加入顺序依次执行下载
    __weak typeof(self) weakSelf = self;
    void(^executeBlock)(void) = ^{
        [weakSelf willEnterDownload:objectArray withPriorityDownload:isPriority];
        if (WXCOIsNilOrNull(block) == NO) {
            block(rejectArray);
        }
    };
    
    if (self.isViaWWAN == YES) { // 如果处于移动网络环境下
        UIAlertController *alertVc = [UIAlertController
                                      alertControllerWithTitle:@"当前正在使用移动数据网络，您确定继续下载吗？"
                                      message:[self getAlertMessageInWWANNetork:objectArray]
                                      preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel
                                                             handler:^(UIAlertAction * _Nonnull action) {
        }];
        UIAlertAction *continueAction = [UIAlertAction actionWithTitle:@"继续下载" style:UIAlertActionStyleDefault
                                                               handler:^(UIAlertAction * _Nonnull action) {
            executeBlock(); // 用户愿意消耗流量
        }];
        [alertVc addAction:cancelAction];
        [alertVc addAction:continueAction];
        [[WXCOUtility getCurrentVC] presentViewController:alertVc animated:YES completion:nil];
    } else { // 如果处于WI-FI网络环境下
        executeBlock();
    }
}

- (void)co_pauseDownload:(NSMutableArray <CODownloadObject *>*)objectArray {
    if (objectArray == nil || objectArray.count <= 0) { // 没发现可以暂停的对象
        [WXCOUtility showHUDWithMessage:@"未发现可暂停的下载"];
        return;
    }
    
    BOOL toastTip = NO; // 是否需要toast提示，只要有一个下载对象需要提示即可
    for (CODownloadObject *object in objectArray) {
        if (object.downloadModel.down_state == stateDownloading || object.downloadModel.down_state == stateWaiting) {
            [object downloadPause:NO]; // 用户手动暂停下载
            if (toastTip == NO) {
                toastTip = object.toastTip;
            }
        }
    }
    // 如果需要提示
    if (toastTip == YES) {
        [WXCOUtility showHUDWithMessage:@"已暂停下载"];
    }
    [self co_processDownloadQueue]; // 推动下载队列继续前进，如果有空闲的下载通道，则可以有新的下载进入
}

- (void)co_deleteDownload:(NSMutableArray <CODownloadObject *>*)objectArray userID:(NSString *)userID {
    if (objectArray == nil || objectArray.count <= 0) { // 没发现可以删除的对象
        [WXCOUtility showHUDWithMessage:@"未发现可删除的下载"];
        return;
    }
    
    BOOL toastTip = NO; // 是否需要toast提示，只要有一个下载对象需要提示即可
    for (CODownloadObject *object in objectArray) {
        [object downloadRemoveWithUserID:userID];
        [self.downloadingQueue removeObject:object];
        [self.allDownloads removeObject:object];
        [self.completeDownloads removeObject:object.downloadModel];
        [self co_removeDownloadFromNetworkChangeCacheArr:object];
        if (toastTip == NO) {
            toastTip = object.toastTip;
        }
    }
    
    // 如果需要提示
    if (toastTip == YES) {
        [WXCOUtility showHUDWithMessage:@"操作成功"];
    }
    [self co_processDownloadQueue]; // 推动下载队列继续前进，如果有空闲的下载通道，则可以有新的下载进入
    [[NSNotificationCenter defaultCenter] postNotificationName:NotiUpdateDownloadInfo object:nil];
}

- (void)co_completeDownload:(CODownloadObject *)object {
    if ([self co_isDownloadCompleted:object] == YES) { // 只有下载完成才从下载队列中移除，还有可能是下载失败，失败的下载对象仍然留在队列里
        [self.completeDownloads addObject:object.downloadModel];
        [self.downloadingQueue removeObject:object];
    }
    [self co_processDownloadQueue];
}

- (void)co_processDownloadQueue {
    NSInteger downloadingCount = 0; // 下载通道中存在正在下载（stateDownloading）的对象数量
    for (CODownloadObject *object in self.downloadingQueue) {
        if (object.downloadModel.down_state == stateDownloading) { // 处理超出下载通道可执行下载的最大并发情况
            downloadingCount++;
            if (downloadingCount > self.maxDownloadCount) { //如果已经达到下载通道并发数量，则被迫进入等待下载状态
                [object downloadPause:YES]; //被其他下载对象插队，暂时进入等待下载
            }
        }
    }
    
    // 如果下载通道还有可有空间，则将等待下载状态下的对象执行下载操作
    while (downloadingCount < self.maxDownloadCount) {
        CODownloadObject *nextObj = [self co_getNextDownloadObjectInQueue];
        if (nextObj == nil) { // 没有发现可被下载的对象，此时下载通道空闲
            break;
        }
        
        [nextObj downloadStart:YES]; //立即开始下载
        downloadingCount++;
    }
}

- (CODownloadObject *)co_getDownloadObjectByUrl:(NSString *)url {
    if (WXCOIsNilOrNull(url) || url.length <= 0) {
        return nil;
    }
    
    for (CODownloadObject *downloadObject in self.allDownloads) {
        if ([downloadObject.downloadModel.down_url isEqualToString:url]) {
            return downloadObject;
        }
    }
    return nil;
}

- (BOOL)co_isDownloadCompleted:(CODownloadObject *)object {
    if (object == nil) {
        return NO;
    }
    
    return [object.downloadModel checkDownloadComplete];
}

- (void)downloadObject2CompleteState:(CODownloadObject *)object {
    if (object == nil) {
        return;
    }
    
    if (object.downloadModel.current_size >= object.downloadModel.total_size) {
        object.downloadModel.down_state = stateCompleted;
        if ([self.downloadingQueue containsObject:object] == NO) { // 下载队列中没有发现object对象，这时通过URL查找
            for (CODownloadObject *downloadingObject in self.downloadingQueue) {
                if ([downloadingObject.downloadModel.down_url isEqualToString:object.downloadModel.down_url]) {
                    object = downloadingObject;
                    break;
                }
            }
        }
        [self.downloadingQueue removeObject:object];
        [self.completeDownloads addObject:object.downloadModel];
        [object.downloadModel updateModel2Database];
    }
}

- (void)co_syncDownRecordForDownloadModel:(CODownloadModel *)model {
    if (model == nil || model.need_sync == needSyncValueNO) { // 模型数据为空，不需要同步;或者是不需要同步
        return;
    }
    
    if (self.syncDownloadHandler == nil) {
        self.syncDownloadHandler = [[SyncDownloadHandler alloc] init];
    }
    
    [self.syncDownloadHandler syncDownloadInfoByDownloadModel:model];
}

- (void)co_completeDownloadSyncSignByLessonId:(NSString *)lessonId {
    if (WXCOIsNilOrNull(lessonId) == YES || lessonId.length <= 0) {
        return;
    }
    
    
    NSArray <CODownloadModel *> *filteredArr = [self.completeDownloads filteredArrayUsingPredicate:
                            [NSPredicate predicateWithFormat:@"lesson_id == %@", lessonId]];
    if (filteredArr == nil || filteredArr.count <= 0)
        return;
    
    for (CODownloadModel *model in filteredArr) {
        model.need_sync = needSyncValueNO;
        [model updateModel2Database];
    }
}

- (void)co_loginSucceedCheckNeedSyncDownload {
    if (self.syncDownloadHandler == nil) {
        self.syncDownloadHandler = [[SyncDownloadHandler alloc] init];
    }
    
    NSArray <CODownloadModel *> *filteredArr = [self.completeDownloads filteredArrayUsingPredicate:
                                                 [NSPredicate predicateWithFormat:@"down_state == %@ and need_sync == %@",
                                                  @(stateCompleted), @(needSyncValueYES)]];
    [self.syncDownloadHandler syncDownloadForLoginSucceed:filteredArr];
}

- (NSMutableArray <CODownloadObject *> *)co_getCompletedDownloadObject:(COLessonType)lessonType {
    if (self.completeDownloads.count <= 0) {
        return [NSMutableArray array];
    }
    
    NSMutableArray <CODownloadObject *> *completeDownloadArr = [NSMutableArray arrayWithCapacity:10];
    [self.allDownloads enumerateObjectsUsingBlock:^(CODownloadObject * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if ((lessonType == NSNotFound || obj.downloadModel.lesson_type == lessonType) &&
            [obj.downloadModel checkDownloadComplete] == YES) {
            [completeDownloadArr addObject:obj];
        }
    }];
    
    return completeDownloadArr;
}

- (NSMutableArray <CODownloadObject *> *)co_getDownloadObjectInDownloadQueue {
    if (self.downloadingQueue.count <= 0) {
        return [NSMutableArray array];
    }
    
    NSMutableArray <CODownloadObject *> *downloadArr = [NSMutableArray arrayWithCapacity:10];
    [self.downloadingQueue enumerateObjectsUsingBlock:^(CODownloadObject * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        [downloadArr addObject:obj];
    }];
    return downloadArr;
}

- (NSInteger)co_getDownloadCompleteNum {
    return self.completeDownloads.count;
}

#pragma mark - Private Methods

/// 记录当前用户可执行下载的数据，先将需要执行下载的数据，记录下来，然后在登录成功后执行恢复下载操作（参考restartDownloadByAppTerminate：）
- (void)co_resetAllDownloadStatus {
    self.lastAppTerminateDownloads = nil;
    NSMutableArray <CODownloadModel *> *modelArray = [NSMutableArray arrayWithCapacity:10];
    for (CODownloadObject *object in self.downloadingQueue) {
        if (object.downloadModel.down_state == stateWaiting || object.downloadModel.down_state == stateDownloading) {
            object.downloadModel.down_state = statePaused;
            [modelArray addObject:object.downloadModel];
            [self.lastAppTerminateDownloads addObject:object];
        }
    }
    
    // 批量更新下载模型数据到本地数据库
    [CODownloadModel batchUpdateDownloadState2Database:modelArray];
}

/// 在下载队列中获取下个可下载的对象
- (CODownloadObject *)co_getNextDownloadObjectInQueue {
    if (self.downloadingQueue.count < 1) { // 下载队列是空的
        return nil;
    }
    
    for (CODownloadObject *object in self.downloadingQueue) {
        if (object.downloadModel.down_state == stateWaiting) { // 返回一个等待下载的对象
            return object;
        }
    }
    
    return nil; // 没有发现可以被执行的下载对象
}

/// 从网络变化数组时移除下载对象
/// @param downObject 要被移除下载对象
- (void)co_removeDownloadFromNetworkChangeCacheArr:(CODownloadObject *)downObject {
    if (self.networkChangeCacheDownloads.count <= 0) { // 网络变化数组是空的
        return;
    }
    
    if ([self.networkChangeCacheDownloads containsObject:downObject] == YES) { // 如果数组中包含了要被移除的对象
        [self.networkChangeCacheDownloads removeObject:downObject];
        return;
    }
}

/// 在WI-FI网络环境下执行下载操作
/// @param downloadObjectArray 要执行下载操作的下载对象集合
- (void)co_willDownloadInWIFINetwork:(NSMutableArray <CODownloadObject *> *)downloadObjectArray {
    if (downloadObjectArray == nil || downloadObjectArray.count < 1) {
        return;
    }
    
    __block NSInteger downloadNum = 0; // 执行下载的个数
    __weak typeof(self) weakSelf = self;
    [downloadObjectArray
     enumerateObjectsUsingBlock:^(CODownloadObject * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
         if (downloadNum < weakSelf.maxDownloadCount) {
            [obj downloadStart:YES];
         } else {
            [obj downloadStart:NO];
         }
         downloadNum++;
     }];
}

/// 在移动网络环境下执行下载操作
/// @param downloadObjectArray 要执行下载操作的下载对象集合
/// @param block 下载操作是否被取消
- (void)co_willDownloadInWWANNetwork:(NSMutableArray <CODownloadObject *> *)downloadObjectArray
                  cancelBlock:(nonnull void(^)(BOOL cancel))block {
    if (downloadObjectArray == nil || downloadObjectArray.count < 1) {
        return;
    }
    
    if (downloadObjectArray.count > 0) { // 如果存在可执行的下载对象，提示用户将要消耗流量
        __block NSInteger downloadNum = 0; // 执行下载的个数
        __weak typeof(self) weakSelf = self;
        
        UIAlertController *alertVc = [UIAlertController
                                      alertControllerWithTitle:@"当前正在使用移动数据网络，继续未完成的下载会消耗较多流量，您确定继续下载吗？"
                                      message:nil preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
            block(YES);
        }];
        UIAlertAction *continueAction = [UIAlertAction actionWithTitle:@"继续下载" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            [downloadObjectArray
             enumerateObjectsUsingBlock:^(CODownloadObject * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                 if (downloadNum < weakSelf.maxDownloadCount) {
                     [obj downloadStart:YES];
                 } else {
                     [obj downloadStart:NO];
                 }
                 downloadNum++;
             }];
            block(NO);
        }];
        [alertVc addAction:cancelAction];
        [alertVc addAction:continueAction];
        [[WXCOUtility getCurrentVC] presentViewController:alertVc animated:YES completion:nil];
    }
}

/// 清空下载数组集合数据
- (void)cleanDownloadArrayData {
    [self.completeDownloads removeAllObjects];
    [self.allDownloads removeAllObjects];
    [self.downloadingQueue removeAllObjects];
    self.networkChangeCacheDownloads = nil;
//    [[COPlaybackDownloadManager sharedInstance] removeAllOffcnLiveDownloadDelegate];
    [CODownloadObject removeAllOffcnLiveDownloadDelegate];
}

/// 将要进入下载操作
/// @param objectArray 下载对象数据的集合
/// @param isPriority 是否是要执行优先下载
- (void)willEnterDownload:(NSMutableArray <CODownloadObject *>*)objectArray withPriorityDownload:(BOOL)isPriority {
    // 将要操作的数组中的正在下载的集合，最多可能会存在maxDownloadCount个
    NSMutableArray *downloadingArray = [NSMutableArray arrayWithCapacity:self.maxDownloadCount];
    BOOL toastTip = NO; // 是否需要toast提示，只要有一个下载对象需要提示即可
    for (CODownloadObject *object in objectArray) {
        if (object.downloadModel.down_state == stateCompleted) { // 如果是已下载完成，不处理
            continue;
        }
        if (object.downloadModel.down_state == stateDownloading) { // 如果当前的下载已在下载中
            if (isPriority == YES) { // 非优先下载的操作，不用对正在下载中对象做处理
                [downloadingArray addObject:object];
            }
        } else {
            [object downloadStart:NO];
            if (isPriority == YES) { // 如果是优先下载
                [self.downloadingQueue removeObject:object]; // 先移除
                [self.downloadingQueue insertObject:object atIndex:0]; // 将下载对象放置在首位，方便下载器优先执行该下载对象
            }
        }
        
        if (toastTip == NO) {
            toastTip = object.toastTip;
        }
    }
    
    // 对优先下载操作时的处理
    if (isPriority == YES) {
        // 本次操作后downloadingArray中除去objectArray外还可以被其他下载对象使用的剩余下载通道
        NSInteger residualCount = MAX(self.maxDownloadCount - objectArray.count, 0);
        // 先暂停不在downloadingArray数组中的正在下载的对象
        for (CODownloadObject *object in self.downloadingQueue) {
            if (object.downloadModel.down_state == stateDownloading) {
                BOOL exist = NO;
                if ([self.downloadingQueue containsObject:object] == YES) { // 一般通过这里就可以找到
                    exist = YES;
                } else {
                    for (CODownloadObject *downloadingObject in downloadingArray) {
                        if ([downloadingObject.downloadModel.down_url isEqualToString:object.downloadModel.down_url] == YES) {
                            exist = YES;
                            break;
                        }
                    }
                }
                
                if (exist == NO) {
                    // objectArray数组外，downloadingArray下载队列还可以占用的下载通道
                    if (residualCount <= 0) { // 如果没有可以使用的下载通道时，则暂时进入等待下载
                        [object downloadPause:YES]; //被其他下载对象插队
                    } else {
                        residualCount --; //objectArray用不了那么多，可以被我霸占一个
                    }
                }
            }
        }
        
        // 剩余可用下载通道里的数量
        NSInteger freeCount = self.maxDownloadCount - downloadingArray.count;
        if (freeCount > 0) {
            for (CODownloadObject *object in objectArray) {
                if (freeCount < 1) {
                    break;
                }
                if (object.downloadModel.down_state == stateWaiting) {
                    freeCount --; // 空闲通道又被霸占了一个
                    [object downloadStart:YES]; //立即开始下载
                }
            }
        }
    }
    
    [self co_processDownloadQueue];
}

/// 获取移动网络下提示框的信息
/// @param objectArray 下载对象数据的集合
/// @return alert弹框message
- (NSString *)getAlertMessageInWWANNetork:(NSMutableArray <CODownloadObject *>*)objectArray {
    int64_t paper_size = 0;
    for (CODownloadObject *object in objectArray) {
        if (object.downloadModel.lesson_type != COLessonTypePdf) { // 一旦发现有一个不是文档类型的下载，立即断开
            paper_size = 0;
            break;
        }
        
        if (object.downloadModel.down_state != stateNoDownload) { // 发现不是新加入的下载，立即断开
            paper_size = 0;
            break;
        }
        
        if (object.downloadModel.total_size <= 0) { // 发现没有拿到试卷的大小，立即断开
            paper_size = 0;
            break;
        }
        
        paper_size += object.downloadModel.total_size;
    }
    
    // 文件大小描述信息
    NSString *message = nil;
    if (paper_size > 0) {
        CGFloat mFileSize = paper_size / 1024.0f / 1024.0f;
        if (mFileSize < 0.1) {
            mFileSize = 0.10;
        }
        message = [NSString stringWithFormat:@"试卷大小：%.1fM",mFileSize];
    }
    return message;
}

#pragma mark - getter setter

- (NSMutableArray <CODownloadObject *> *)allDownloads {
    if (_allDownloads == nil) {
        _allDownloads = [NSMutableArray <CODownloadObject *> arrayWithCapacity:10];
    }
    return _allDownloads;
}

- (NSMutableArray <CODownloadModel *> *)completeDownloads {
    if (_completeDownloads == nil) {
        _completeDownloads = [NSMutableArray <CODownloadModel *> arrayWithCapacity:10];
    }
    return _completeDownloads;
}

- (NSMutableArray <CODownloadObject *> *)downloadingQueue {
    if (_downloadingQueue == nil) {
        _downloadingQueue = [NSMutableArray <CODownloadObject *> arrayWithCapacity:10];
    }
    return _downloadingQueue;
}

- (NSMutableArray <CODownloadObject *> *)networkChangeCacheDownloads {
    if (_networkChangeCacheDownloads == nil) {
        _networkChangeCacheDownloads = [NSMutableArray <CODownloadObject *> arrayWithCapacity:10];
    }
    return _networkChangeCacheDownloads;
}

- (NSMutableArray <CODownloadObject *> *)lastAppTerminateDownloads {
    if (_lastAppTerminateDownloads == nil) {
        _lastAppTerminateDownloads = [NSMutableArray <CODownloadObject *> arrayWithCapacity:10];
    }
    return _lastAppTerminateDownloads;
}

- (NSMutableArray <CODownloadModel *> *)newDownloadModels {
    if (_newDownloadModels == nil) {
        _newDownloadModels = [NSMutableArray <CODownloadModel *> arrayWithCapacity:10];
    }
    return _newDownloadModels;
}

@end
