//
//  CloudStorageUploadCenter.m
//  zhuxun
//
//  Created by winsoft on 17/6/26.
//
//

#import "CloudStorageUploadCenter.h"
//#import "WSUploadSession.h"
#import <MJExtension/MJExtension.h>
#import "HttpRequest.h"
#import "CloudStorageDB.h"

#import "CSFileModel.h"

@interface CloudStorageUploadCenter()

@property (nonatomic, strong) NSOperationQueue *taskQueue;

@property (nonatomic , assign) CGFloat maxConcurrenceUploadCount;
/**
 *  同时最大文件上传并发数
 */

@property (nonatomic , strong) NSMutableDictionary *maxConcurrenceUploadTasks;//downloadmodel.

/**
 *  全部除正在上传的其他所有上传任务
 */
@property (nonatomic , strong) NSMutableDictionary *totalUploadModels;

/**
 *  上一个新增的model.
 */
@property (nonatomic , strong) CSFileDownUpModel *lastOneDowunUpModel; // last one = nil;
@property (nonatomic , strong) CSFileDownUpModel *firstOneDowunUpModel;
@end
@implementation CloudStorageUploadCenter
static CloudStorageUploadCenter *cloudStorageUploadCenter;

+ (instancetype)sharedInstance
{
    static dispatch_once_t onceToken;
    
    dispatch_once(&onceToken, ^{
        cloudStorageUploadCenter = [[self alloc] init];
    });
    
    return cloudStorageUploadCenter;
}

- (void)userServerOut
{
    for ( CloudUploadSession *cloudUploadingSession  in self.maxConcurrenceUploadTasks.allValues) {
        [cloudUploadingSession cancerUpload];
    }
    
    [self.maxConcurrenceUploadTasks removeAllObjects];
    [self.totalUploadModels removeAllObjects];
    self.firstOneDowunUpModel = nil;
    self.lastOneDowunUpModel = nil;
}

- (instancetype)init
{
    if (self = [super init]) {
        
        _totalUploadModels = [NSMutableDictionary dictionary];
        _maxConcurrenceUploadTasks = [NSMutableDictionary dictionary];
        
        _taskQueue = [NSOperationQueue new];
        //线程数量最大值
        _taskQueue.maxConcurrentOperationCount = self.maxConcurrenceUploadCount;
    }
    
    return self;
}


//-(NSOperationQueue *)taskQueue
//{
//    //    if(!_taskQueue)
//    //        {
//    _taskQueue = [NSOperationQueue new];
//    //线程数量最大值
//    _taskQueue.maxConcurrentOperationCount = self.maxConcurrenceUploadCount;
//    //    }
//
//    return _taskQueue;
//}



- (CGFloat)maxConcurrenceUploadCount
{
    //数据库设计..
    return 1;
}

//获取md5+name 的operation
- (BOOL)judgeSameFileIsProcessWithFileDownUpModel:(CSFileDownUpModel *)fileDownUpModel
{
    BOOL hasSameFile = NO;
    
    NSString *searchNameAndMd5= [NSString stringWithFormat:@"%@_%@",[fileDownUpModel.downUpUUID componentsSeparatedByString:@"_"][0],[fileDownUpModel.downUpUUID componentsSeparatedByString:@"_"][1]];
    
    //self.name,self.md5  name_md5
    for (NSString *allUUID in self.maxConcurrenceUploadTasks.allKeys) {
        
        if ([searchNameAndMd5 isEqualToString:allUUID]) {
            
            hasSameFile = YES;
            break;
        }else continue;
        
        
    }
    
    return hasSameFile;
}

- (NSString *)getTrueFileNmae_Md5:(CSFileDownUpModel *)csFileDownUpModel
{
    NSString *searchNameAndMd5= [NSString stringWithFormat:@"%@_%@",csFileDownUpModel.name,csFileDownUpModel.md5];
    return searchNameAndMd5;
}

- (void)addOneFileToUpdateWithCSFileDownUpModel:(CSFileDownUpModel *)fileDownUpModel
{
    //判断是否重复
    if ([self.totalUploadModels objectForKey:fileDownUpModel.downUpUUID] || [self.maxConcurrenceUploadTasks objectForKey: [self getTrueFileNmae_Md5:fileDownUpModel]]) {
        return;
    }
    //无论成功还是失败还是暂停,都要对队列进行重新排序
    
    //进行队列初始化.,如果其中排队的某个暂停,则对其进行重新排队. a->b->c ,if b pause, a.next = b.next
    
    
    if (_lastOneDowunUpModel != fileDownUpModel && _lastOneDowunUpModel) {
        
        _lastOneDowunUpModel.nextFileDownUpModel = fileDownUpModel;
        fileDownUpModel.lastFileDownUpModel = _lastOneDowunUpModel;
    }
    
    if (!_firstOneDowunUpModel) {
        _firstOneDowunUpModel = fileDownUpModel;
    }
    
    _lastOneDowunUpModel = fileDownUpModel;
    
    DownUpStatus oldStatus = fileDownUpModel.downUpStatus;
    
    fileDownUpModel.downUpStatus = DownUpStatusWait;
    
    [self.totalUploadModels setObject:fileDownUpModel forKey:fileDownUpModel.downUpUUID];
    
    if (self.maxConcurrenceUploadTasks.allKeys.count < self.maxConcurrenceUploadCount) {
        
        [self startUploadFileWithFileDownUpModel:fileDownUpModel];
    }
    
    ////filemodelstatus change,save.
    if (oldStatus != fileDownUpModel.downUpStatus) {
        [kCloudStorageDB updateCSDownUpFileStatusWithCSFileDownUpModel:fileDownUpModel];
    }
    
    
}

#warning 2017-06-29 下一阶段:队列上传.
- (void)startUploadFileWithFileDownUpModel:(CSFileDownUpModel *)fileDownUpModel
{
    //    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1*NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    
    if (!fileDownUpModel) {
        return;
    }
    
    __weak typeof(self)weakSelf = self;
    //待存储.并通知translistcontroller.
    fileDownUpModel.downUpStatus = DownUpStatusDoing;
    
    //存储数据库.
    CloudUploadSession *cloudUploadSession = nil;
    
    if ([self judgeSameFileIsProcessWithFileDownUpModel:fileDownUpModel]) {
        
        cloudUploadSession = [self.maxConcurrenceUploadTasks objectForKey:[self getTrueFileNmae_Md5:fileDownUpModel]];
        
    }else {
        cloudUploadSession= [CloudUploadSession startUploadFileWithFileDownUpModel:fileDownUpModel operationQueue:self.taskQueue];
        
        [self.maxConcurrenceUploadTasks setObject:cloudUploadSession forKey: [self getTrueFileNmae_Md5:fileDownUpModel]];
    }
    
    
    //云盘赋值失败怎么办.,移动至cloud..session.
    cloudUploadSession.uploadSuccessDBBlock = ^(NSString* url,long long fileSize,CSFileDownUpModel *fileDownUpModel){
        
        //重新排队
        if (fileDownUpModel.lastFileDownUpModel && fileDownUpModel.nextFileDownUpModel) {
            
            fileDownUpModel.lastFileDownUpModel.nextFileDownUpModel = fileDownUpModel.nextFileDownUpModel;
            
            fileDownUpModel.nextFileDownUpModel.lastFileDownUpModel = fileDownUpModel.lastFileDownUpModel;
        }else if (fileDownUpModel.nextFileDownUpModel && !fileDownUpModel.lastFileDownUpModel)
        {
            //只有下一个,没有上一个,说明是队头,
            
            //移除下一个的上一个,即指定下一个为头.
            fileDownUpModel.nextFileDownUpModel.lastFileDownUpModel = nil;
            
            weakSelf.firstOneDowunUpModel = fileDownUpModel.nextFileDownUpModel;
            
        }
        
        //待使用category.反之key=nil的情况.
        [self.totalUploadModels removeObjectForKey:fileDownUpModel.downUpUUID];
        
        if ([_firstOneDowunUpModel.downUpUUID isEqualToString:fileDownUpModel.downUpUUID]) {
            _firstOneDowunUpModel = nil;
        }
        
        if ([_lastOneDowunUpModel.downUpUUID isEqualToString:fileDownUpModel.downUpUUID]) {
            _lastOneDowunUpModel = nil;
        }
        
        
        [weakSelf.maxConcurrenceUploadTasks removeObjectForKey:[weakSelf getTrueFileNmae_Md5:fileDownUpModel] ];
        
        [weakSelf.totalUploadModels removeObjectForKey:fileDownUpModel.downUpUUID];
        
        //        [weakSelf queueForTaskNextWithFinishedModel:weakSelf.firstOneDowunUpModel];
        [weakSelf queueForMuiltTastWithFinishedModel:weakSelf.firstOneDowunUpModel currentMaxTaskCount:weakSelf.maxConcurrenceUploadTasks.allValues.count];
        
        //        [CloudStorageDB updateCSDownUpFileStatusWithCSFileDownUpModel:fileDownUpModel];
        
        
    };
    cloudUploadSession.uploadFailedDBBlock = ^(NSString* errMessage,CSFileDownUpModel *fileDownUpModel){
        
        //重新排队
        if (fileDownUpModel.lastFileDownUpModel && fileDownUpModel.nextFileDownUpModel) {
            
            fileDownUpModel.lastFileDownUpModel.nextFileDownUpModel = fileDownUpModel.nextFileDownUpModel;
            
            fileDownUpModel.nextFileDownUpModel.lastFileDownUpModel = fileDownUpModel.lastFileDownUpModel;
        }else if (fileDownUpModel.nextFileDownUpModel && !fileDownUpModel.lastFileDownUpModel)
        {
            //只有下一个,没有上一个,说明是队头,
            
            //移除下一个的上一个,即指定下一个为头.
            fileDownUpModel.nextFileDownUpModel.lastFileDownUpModel = nil;
            
            weakSelf.firstOneDowunUpModel = fileDownUpModel.nextFileDownUpModel;
            
        }
        
        //待使用category.反之key=nil的情况.
        [self.totalUploadModels removeObjectForKey:fileDownUpModel.downUpUUID];
        
        if ([_firstOneDowunUpModel.downUpUUID isEqualToString:fileDownUpModel.downUpUUID]) {
            _firstOneDowunUpModel = nil;
        }
        
        if ([_lastOneDowunUpModel.downUpUUID isEqualToString:fileDownUpModel.downUpUUID]) {
            _lastOneDowunUpModel = nil;
        }
        
        [weakSelf.maxConcurrenceUploadTasks removeObjectForKey: [self getTrueFileNmae_Md5:fileDownUpModel]];
        
        [weakSelf.totalUploadModels removeObjectForKey:fileDownUpModel.downUpUUID];
        
        [weakSelf queueForMuiltTastWithFinishedModel:weakSelf.firstOneDowunUpModel currentMaxTaskCount:weakSelf.maxConcurrenceUploadTasks.allValues.count];
        
    };
    
    cloudUploadSession.uploadProgressDBBlock = ^(double progress,NSInteger sendedSize, CSFileDownUpModel *fileDownUpModel){
        
        //         [CloudStorageDB updateCSDownUpFileStatusWithCSFileDownUpModel:fileDownUpModel];
    };
    
    //通知上传下载列表进行更新.
    if (self.fileUpStatusChangeBlock) {
        self.fileUpStatusChangeBlock(fileDownUpModel);
    }
    
    
    //    });
    
    
    
}

//开始下一个任务
//- (void)queueForTaskNextWithFinishedModel:(CSFileDownUpModel *)csfileDownUpModel
//{
//#warning next.last = nil ???..
//    __weak typeof(self)weakSelf = self;
//    if (csfileDownUpModel.downUpStatus == DownUpStatusWait && csfileDownUpModel) {
//        [self startUploadFileWithFileDownUpModel:csfileDownUpModel];
//    }else{
//
//        //递归获取nextwait
//        [self getQueueUntileWaitTaskWithFinishedModel:csfileDownUpModel resultBlock:^(CSFileDownUpModel *nextFileDownUpModel) {
//
//            if (nextFileDownUpModel) {
//                [weakSelf startUploadFileWithFileDownUpModel:nextFileDownUpModel];
//            }
//
//
//        }];
//    }
//
//}

- (void)queueForMuiltTastWithFinishedModel:(CSFileDownUpModel *)csfileDownUpModel currentMaxTaskCount:(NSInteger)currentMaxTaskCount
{
    __weak typeof(self)weakSelf = self;
    
    if (currentMaxTaskCount < self.maxConcurrenceUploadCount) {
        
        if (csfileDownUpModel.downUpStatus == DownUpStatusWait && csfileDownUpModel ) {
            
            [self startUploadFileWithFileDownUpModel:csfileDownUpModel];
            [self queueForMuiltTastWithFinishedModel:csfileDownUpModel.nextFileDownUpModel currentMaxTaskCount:currentMaxTaskCount + 1];
        }else{
            
            //递归获取nextwait
            
            [self getQueueUntileWaitTaskWithFinishedModel:csfileDownUpModel resultBlock:^(CSFileDownUpModel *nextFileDownUpModel) {
                
                if (nextFileDownUpModel) {
                    
                    [weakSelf startUploadFileWithFileDownUpModel:nextFileDownUpModel];
                    [weakSelf queueForMuiltTastWithFinishedModel:csfileDownUpModel.nextFileDownUpModel currentMaxTaskCount:currentMaxTaskCount + 1];
                }
                
                
            }];
        }
        
    }
    
}

//查询下一个任务
- (void)getQueueUntileWaitTaskWithFinishedModel:(CSFileDownUpModel *)csfileDownUpModel resultBlock:(void(^)(CSFileDownUpModel *csfileDownUpModel))resultBlock
{
    
    
    if (csfileDownUpModel.nextFileDownUpModel) {
        if (csfileDownUpModel.nextFileDownUpModel.downUpStatus == DownUpStatusDoing) {
            
            csfileDownUpModel = csfileDownUpModel.nextFileDownUpModel;
            
            [self getQueueUntileWaitTaskWithFinishedModel:csfileDownUpModel resultBlock:resultBlock];
            
        }else if(csfileDownUpModel.nextFileDownUpModel.downUpStatus == DownUpStatusWait)resultBlock(csfileDownUpModel.nextFileDownUpModel);
        
    }else resultBlock(nil);
    
    
}

- (void)registeUploadForUIWithcsFileDownUpModel:(CSFileDownUpModel *)csFileDownUpModel ProcessBlock:(CSUploadProgressUIBlock)processBlock successBlock:(CSUploadSuccessUIBlock)successBlock failBlock:(CSUploadFailedUIBlock)failBlock
{
    CloudUploadSession *cloudUploadSession = [self.maxConcurrenceUploadTasks objectForKey:[self getTrueFileNmae_Md5:csFileDownUpModel]];
    
    if (cloudUploadSession) {
        
        [cloudUploadSession addBlockToUIWithUUID:csFileDownUpModel.downUpUUID withProcessBlock:processBlock successBlock:successBlock failBlock:failBlock];
        
    }
}


- (void)updateOneUploadStatusWithcsfileDownUpModel:(CSFileDownUpModel *)csfileDownUpModel downUpStatus:(DownUpStatus)downUpStatus
{
    if (downUpStatus == DownUpStatusWait) {
        
        [self addOneFileToUpdateWithCSFileDownUpModel:csfileDownUpModel];
    }else{
        
        //排队中的情况
        CSFileDownUpModel *oldFilDownUpModel = [self.totalUploadModels objectForKey:csfileDownUpModel.downUpUUID];
        //下载中的情况
        CloudUploadSession *cloudUploadingSession = [self.maxConcurrenceUploadTasks objectForKey:[self getTrueFileNmae_Md5:csfileDownUpModel]];
        
        if (cloudUploadingSession) {
            
            [cloudUploadingSession cancerUpload];
            
            [self.maxConcurrenceUploadTasks removeObjectForKey: [self getTrueFileNmae_Md5:csfileDownUpModel]];
        }
        
        if (oldFilDownUpModel)
        {
            //重新排队,有问题.
            if (oldFilDownUpModel.lastFileDownUpModel && oldFilDownUpModel.nextFileDownUpModel) {
                
                oldFilDownUpModel.lastFileDownUpModel.nextFileDownUpModel = oldFilDownUpModel.nextFileDownUpModel;
                
                oldFilDownUpModel.nextFileDownUpModel.lastFileDownUpModel = oldFilDownUpModel.lastFileDownUpModel;
            }else if (oldFilDownUpModel.nextFileDownUpModel && !oldFilDownUpModel.lastFileDownUpModel)
            {
                //只有下一个,没有上一个,说明是队头,
                
                //移除下一个的上一个,即指定下一个为头.
                oldFilDownUpModel.nextFileDownUpModel.lastFileDownUpModel = nil;
                
                self.firstOneDowunUpModel = oldFilDownUpModel.nextFileDownUpModel;
                
            }
            
            //待使用category.反之key=nil的情况.
            [self.totalUploadModels removeObjectForKey:oldFilDownUpModel.downUpUUID];
            
            if ([_firstOneDowunUpModel.downUpUUID isEqualToString:oldFilDownUpModel.downUpUUID]) {
                _firstOneDowunUpModel = nil;
            }
            
            if ([_lastOneDowunUpModel.downUpUUID isEqualToString:oldFilDownUpModel.downUpUUID]) {
                _lastOneDowunUpModel = nil;
            }
            
            
            [self.totalUploadModels removeObjectForKey:csfileDownUpModel.downUpUUID];
            
            //开始下一个任务
            [self queueForMuiltTastWithFinishedModel:self.firstOneDowunUpModel currentMaxTaskCount:self.maxConcurrenceUploadTasks.allValues.count];
            //            [self queueForTaskNextWithFinishedModel:self.firstOneDowunUpModel];
            
        }
        
        
    }
    
}


- (void)updateUploadStatusWithcsfileDownUpModels:(NSArray <CSFileDownUpModel *> *)csfileDownUpModels downUpStatus:(DownUpStatus)downUpStatus
{
    __weak typeof(self)weakself = self;
    //1.全部暂停的,则全部移除队列并且重新排序.
    //2.全部开始的,则直接addin队列
    if (downUpStatus == DownUpStatusWait) {
        
        for (CSFileDownUpModel *csfileDownUpModel in csfileDownUpModels){
            
            [self addOneFileToUpdateWithCSFileDownUpModel:csfileDownUpModel];
            
        }
        
    }else{
        
        
        //先移除进行中的任务
        for (CSFileDownUpModel *csfileDownUpModel in csfileDownUpModels){
            
            CSFileDownUpModel *oldFilDownUpModel = [self.totalUploadModels objectForKey:csfileDownUpModel.downUpUUID];
            
            CloudUploadSession *cloudUploadingSession = [self.maxConcurrenceUploadTasks objectForKey: [self getTrueFileNmae_Md5:csfileDownUpModel]];
            
            if (cloudUploadingSession) {
                
                [cloudUploadingSession cancerUpload];
                
                [self.maxConcurrenceUploadTasks removeObjectForKey: [self getTrueFileNmae_Md5:csfileDownUpModel]];
            }
            
            if (oldFilDownUpModel) {
                
                //重新排队
                if (oldFilDownUpModel.lastFileDownUpModel && oldFilDownUpModel.nextFileDownUpModel) {
                    
                    oldFilDownUpModel.lastFileDownUpModel.nextFileDownUpModel = oldFilDownUpModel.nextFileDownUpModel;
                    
                    oldFilDownUpModel.nextFileDownUpModel.lastFileDownUpModel = oldFilDownUpModel.lastFileDownUpModel;
                }else if (oldFilDownUpModel.nextFileDownUpModel && !oldFilDownUpModel.lastFileDownUpModel)
                {
                    //只有下一个,没有上一个,说明是队头,
                    
                    //移除下一个的上一个,即指定下一个为头.
                    oldFilDownUpModel.nextFileDownUpModel.lastFileDownUpModel = nil;
                    
                    weakself.firstOneDowunUpModel = oldFilDownUpModel.nextFileDownUpModel;
                    
                }
                
                //待使用category.反之key=nil的情况.
                [self.totalUploadModels removeObjectForKey:csfileDownUpModel.downUpUUID];
                
                if ([_firstOneDowunUpModel.downUpUUID isEqualToString:csfileDownUpModel.downUpUUID]) {
                    _firstOneDowunUpModel = nil;
                }
                
                if ([_lastOneDowunUpModel.downUpUUID isEqualToString:csfileDownUpModel.downUpUUID]) {
                    _lastOneDowunUpModel = nil;
                }
            }
            
        }
        
        
        [self queueForMuiltTastWithFinishedModel:self.firstOneDowunUpModel currentMaxTaskCount:self.maxConcurrenceUploadTasks.allValues.count];
        
        
        
    }
    
    if (downUpStatus !=  DownUpStatusDelete) {
        
        [kCloudStorageDB updateCSDownUpFileStatusWithCSFileDownUpModels:csfileDownUpModels downUpType:DownUpModelDown downUpStatus:downUpStatus];
        
    }
    
    
}

@end
