//
//  downloadManager.m
//  隐私保护
//
//  Created by xd h on 2024/1/9.
//

#import "downloadManager.h"
#import "cachesFileManager.h"
#import <sys/mount.h>
#include <sys/param.h>

@interface downloadManager ()
/**检测任务10s后 无反馈重新开始 */
@property (nonatomic, assign) NSInteger  taskRenewTime; //
@end

@implementation downloadManager
static downloadManager * cur_downloadManager = nil;
+(downloadManager *)shareInstance;
{
    static dispatch_once_t onceToken;
    
    dispatch_once(&onceToken, ^{
        cur_downloadManager = [[downloadManager alloc] init];
        
    });
    
    return cur_downloadManager;
}

- (id)init
{
    self = [super init];
    
    if (self) {
        //[self initManager];
    }
    
    return self;
}


#pragma mark 读取数据库数据
- (void)getDataInDatabaseFun:(BOOL)isReGet complete:(custom_complete_Arr)complete
{
    if(_databaseArr && _databaseArr.count == 3 && !isReGet){
        complete(_databaseArr);
        return;
    }
    
    if(!_databaseArr)
    {
        _databaseArr = [NSMutableArray new];
    }
    
    //KWeakSelf
    //dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
        [couldPhoneFileModel bg_findAsync:download_tableName limit:0 orderBy:nil desc:NO complete:^(NSArray * _Nullable array) {
            NSMutableArray *failArr = [NSMutableArray new];
            NSMutableArray *doneArr = [NSMutableArray new];
            NSMutableArray *otherArr = [NSMutableArray new];
            
                for (couldPhoneFileModel * curModel in array) {
                
                    if(curModel.curDownloadStateType == downloadStateFail){
                        [failArr addObject:curModel];
                    }
                    else if(curModel.curDownloadStateType == downloadStateDone){
                        [doneArr addObject:curModel];
                    }
                    else{
                        [otherArr addObject:curModel];
                    }
                }
            
            NSLock *lock = [NSLock new];
            [lock lock];
            
            NSMutableArray *newArr = [NSMutableArray new];
            [newArr addObject:otherArr];
            [newArr addObject:doneArr];
            [newArr addObject:failArr];
            self->_databaseArr = newArr;
            
            [lock unlock];
            
            complete(self->_databaseArr);
        }];
    //});

}

-(void)handleCouldPhoneFileModelToDownloadFileDataFunBy:(NSMutableArray*)indexPathsForSelectedItems complete:(custom_complete_Arr)complete
{
    if(!indexPathsForSelectedItems && indexPathsForSelectedItems.count == 0){
        complete(nil);
        return;
    }
    
    for (couldPhoneFileModel*model in indexPathsForSelectedItems) {
        model.bg_tableName = download_tableName;
    }
    
    _isNewAddTaskType = YES;
    
    KWeakSelf
    //查
    [self getDataInDatabaseFun:YES complete:^(NSMutableArray * _Nonnull Arr) {
        //排重
        NSMutableArray *newDownArr = [weakSelf  checkDownloadTaskRepeatFun:indexPathsForSelectedItems];
        
        if(newDownArr.count>0){
            //存
            [couldPhoneFileModel bg_saveOrUpdateArrayAsync:newDownArr complete:^(BOOL isSuccess) {
                //再查
                [weakSelf getDataInDatabaseFun:YES complete:^(NSMutableArray * _Nonnull Arr) {
                    complete(Arr);
                    [weakSelf planToDownloadFileFun];
                }];
            }];
        }
        else{
            complete(Arr);
            [weakSelf planToDownloadFileFun];
        }
        
    }];
}

#pragma mark 检测是否有下载任务重复
- (NSMutableArray*)checkDownloadTaskRepeatFun:(NSMutableArray*)indexPathsForSelectedItems
{
    if(!_databaseArr || _databaseArr.count != 3){
        return indexPathsForSelectedItems;
    }
    
    NSMutableArray *downloadArr = _databaseArr[0];
    NSMutableArray *newTaskArr = [NSMutableArray new];
    
    for (couldPhoneFileModel*model in indexPathsForSelectedItems) {
       NSString *fileName = [model getFileNameFun];
        
        BOOL isNeedAddType = YES;
        for (couldPhoneFileModel* hadModel in downloadArr) {
            NSString *hadFileName = [hadModel getFileNameFun];
            if([fileName isEqualToString:hadFileName]){
                isNeedAddType = NO;
                break;
            }
        }
        
        if(isNeedAddType){
            [newTaskArr addObject:model];
        }
    }
    
    return newTaskArr;
}

- (void)planToDownloadFileFun
{
    if(!_databaseArr || _databaseArr.count != 3){
        return;
    }
    
    _downLoadFileModelDataArr = _databaseArr[0];
    
    [self beginDownloadFileFun];
}


- (BOOL)checkFreeDiskSpaceInBytesIsOK:(long)fileByte{
    struct statfs buf;
    unsigned long long freeSpace = -1;
    if (statfs("/var", &buf) >= 0) {
        freeSpace = (unsigned long long)(buf.f_bsize * buf.f_bavail);
    }
    
    long space = freeSpace - fileByte;
    if( space/fileByte < 2.0 || space < 500*1024*1024){
        return NO;
    }
    
    return YES;
}

- (void)beginDownloadFileFun
{
    if(_downLoadFileModelDataArr.count == 0)
    {
        _curDownloadFileModel = nil;
        
        [self didDownloadAllTaskDoneFun];
        return;
    }
    
    self.taskRenewTime = [iTools getNowTimeStamp];
    
    _isSuspendType = NO;
    _isDownloadIngType = YES;
    
    if(_reDownloadIngSelectIndex > 0
       && _reDownloadIngSelectIndex < _downLoadFileModelDataArr.count){
        _curDownloadFileModel = _downLoadFileModelDataArr[_reDownloadIngSelectIndex];
    }
    else
    {
        _curDownloadFileModel = _downLoadFileModelDataArr.firstObject;
    }
    
    
    if(!_curDownloadFileModel){
        return;
    }
    
    //做个异常处理
    if(_databaseArr.count == 3 && _isNewAddTaskType){
        NSMutableArray *downloadIngArr = _databaseArr[0];
        if(_downLoadFileModelDataArr.count != downloadIngArr.count){
            _databaseArr[0] = _downLoadFileModelDataArr;
        }
    }
    
    if(![self checkFreeDiskSpaceInBytesIsOK:_curDownloadFileModel.length]){
        mainBlock(^{
            [[iToast makeText:NSLocalizedString(@"phone_space_Insufficient",nil)] show];
        });
        return;
    }
    
    _curDownloadFileModel.curDownloadStateType = downloadStateUploading;
    
    [[NSNotificationCenter defaultCenter] postNotificationName:downloadFileBeginNotification object:_curDownloadFileModel];
}

- (void)DownloadFileDoneOneFileFun
{
    self.taskRenewTime = [iTools getNowTimeStamp];
    
    _curDownloadFileModel.curDownloadStateType = downloadStateDone;
//    NSString *fileName = [_curDownloadFileModel getFileNameFun];
//    [cachesFileManager removeItemAtPath:fileName type:DownLoadFileType error:nil];
    
   
    [self DownloadFileChangeingOneFileFun];
    
    if(_isSuspendType){
        return;
    }
    [self beginDownloadFileFun];
}

- (void)DownloadFileFailOneFileFun
{
    self.taskRenewTime = [iTools getNowTimeStamp];
    
    _curDownloadFileModel.curDownloadStateType = downloadStateFail;
      
    [self DownloadFileChangeingOneFileFun];
    
    if(_isSuspendType){
        return;
    }
    [self beginDownloadFileFun];
}

- (void)DownloadFileChangeingOneFileFun
{
    self.taskRenewTime = [iTools getNowTimeStamp];
    
    if(_curDownloadFileModel.curDownloadStateType == downloadStateDone){
        [_downLoadFileModelDataArr removeObject:_curDownloadFileModel];
        [self handleDatabaseArrDeleteObjectInDownloading:_curDownloadFileModel];
        
        [self handleDatabaseArrAddObjectInDone:_curDownloadFileModel];
    }
    else if(_curDownloadFileModel.curDownloadStateType == uploadStateFail){
        [_downLoadFileModelDataArr removeObject:_curDownloadFileModel];
        
        [self handleDatabaseArrDeleteObjectInDownloading:_curDownloadFileModel];
        [self handleDatabaseArrAddObjectInFail:_curDownloadFileModel];
    }

    [_curDownloadFileModel bg_saveOrUpdateAsync:^(BOOL isSuccess) {
        //HLog(@"%@ 写入 %@", model.filename, isSuccess ? @"成功":@"失败");
    }];
        
    
    if(!_isSuspendType || _curDownloadFileModel.curDownloadStateType != uploadStateSuspend){
        [[NSNotificationCenter defaultCenter] postNotificationName:downloadFileRefreshNotification object:_curDownloadFileModel];
    }
    
}



- (void)handleDatabaseArrDeleteObjectInDownloading:(couldPhoneFileModel*)model
{
    NSLock *lock = [NSLock new];
    [lock lock];
    if(_databaseArr && _databaseArr.count == 3 ){
        
        NSMutableArray *ingArr = _databaseArr[0];
        NSInteger count = ingArr.count;
        [ingArr removeObject:model];
        
        NSInteger atferDelCount = ingArr.count;
        
        if(count == atferDelCount){
            for (couldPhoneFileModel*preModel in ingArr) {
                if(preModel.bg_id.integerValue == model.bg_id.integerValue){
                    [ingArr removeObject:preModel];
                    break;
                }
            }
        }
        
        NSInteger atferDelCount2 = ingArr.count;
        
        if(count == atferDelCount2){
            
           // HLog(@"\n\n\nerror:下载中的任务没有删除掉database bgid:%@\n\n\n\n",model.bg_id);
        }
        
    }
    [lock unlock];
}

- (void)handleDatabaseArrAddObjectInDone:(couldPhoneFileModel*)model
{
    NSLock *lock = [NSLock new];
    [lock lock];
    if(_databaseArr && _databaseArr.count == 3 ){
        NSMutableArray *doneArr = _databaseArr[1];
        [doneArr insertObject:model atIndex:0];
    }
    [lock unlock];
}

- (void)handleDatabaseArrAddObjectInFail:(couldPhoneFileModel*)model
{
    NSLock *lock = [NSLock new];
    [lock lock];
    if(_databaseArr && _databaseArr.count == 3 ){
        NSMutableArray *failArr = _databaseArr[2];
        [failArr insertObject:model atIndex:0];
    }
    [lock unlock];
}

- (void)suspendDownloadFileFun:(BOOL)isSuspendAll
{
    _isSuspendType = YES;
    
    if(isSuspendAll){
        for (couldPhoneFileModel *couldPhoneFileMod in _downLoadFileModelDataArr) {
            couldPhoneFileMod.curDownloadStateType = downloadStateSuspend;
        }
        
    }
}

- (void)reDownloadFileFunBy:(NSMutableArray*)Arr withAll:(BOOL)isAllType
{
    if(!_downLoadFileModelDataArr){
        _downLoadFileModelDataArr = [NSMutableArray new];
    }
    
    if(isAllType)
    {
        _isNewAddTaskType = YES;
        _downLoadFileModelDataArr = Arr;
        _reDownloadIngSelectIndex = -1;
        [self beginDownloadFileFun];
        return;
    }
    
    _isNewAddTaskType = NO;
    _reDownloadIngSelectIndex = 0;
    
    NSMutableArray *curArr = [NSMutableArray arrayWithArray:Arr];
    _downLoadFileModelDataArr = curArr;
    
//    for (uploadFileDataModel*addModel in Arr) {
//        
//        BOOL needAddModel = YES;
//        
//        for (int i=0;i< _downLoadFileModelDataArr.count;i++)
//        {
//            couldPhoneFileModel*preModel = _downLoadFileModelDataArr[i];
//            
//            if(addModel.bg_id.integerValue == preModel.bg_id.integerValue)
//            {
//                needAddModel = NO;
//                
//                if(_reDownloadIngSelectIndex == 0){
//                    _reDownloadIngSelectIndex = i;
//                    
//                    if(i==0){
//                        _reDownloadIngSelectIndex = -1;
//                    }
//                }
//                
//                break;
//            }
//        }
//        
//        if(needAddModel){
//            [_downLoadFileModelDataArr addObject:addModel];
//            _reDownloadIngSelectIndex = _downLoadFileModelDataArr.count -1;
//        }
//    }
    
    [self beginDownloadFileFun];
}

- (void)handleDatabaseArrByDelete:(couldPhoneFileModel*)delModel
{
    if(_databaseArr && _databaseArr.count == 3 ){
        
        if(delModel.curDownloadStateType == downloadStateDone)
        {
            NSMutableArray *arr = _databaseArr[1];
            [arr removeObject:delModel];
        }
        else if(delModel.curDownloadStateType == downloadStateFail){
            NSMutableArray *arr = _databaseArr[2];
            [arr removeObject:delModel];
        }
        else{
            NSMutableArray *arr = _databaseArr[0];
            [arr removeObject:delModel];
        }
    }
}


- (void)deleteDownloadFileRecordBy:(NSMutableArray *)delArr withDelCache:(BOOL)isDelCache
{
    //逻辑待优化
    BOOL isSuc = false;
    
    BOOL isDelUploadingModel = false;
    
    NSMutableArray *curDelArr = [NSMutableArray arrayWithArray:delArr];
    for (couldPhoneFileModel *couldPhoneFileMod in curDelArr) {
        
        NSMutableString* where = [[NSMutableString alloc] initWithString:@"where "];
        
        NSString *curStr =  [NSString stringWithFormat:@"%@=%@ ",bg_sqlKey(@"bg_id"),bg_sqlValue(couldPhoneFileMod.bg_id)];
        [where appendString:curStr];
        
        [couldPhoneFileModel bg_deleteAsync:download_tableName where:where complete:^(BOOL isSuccess) {
        }];
       
       //isSuc =  [couldPhoneFileModel bg_delete:download_tableName where:where];
        
        [self handleDatabaseArrByDelete:couldPhoneFileMod];
        
        if(couldPhoneFileMod.bg_id.integerValue == _curDownloadFileModel.bg_id.integerValue){
            isDelUploadingModel = YES;
            [self suspendDownloadFileFun:NO];
        }

    }
    
    if(isDelUploadingModel){
        _isDownloadIngType = NO;
        if(_downLoadFileModelDataArr > 0){
            [self beginDownloadFileFun];
        }
    }
    
    [[NSNotificationCenter defaultCenter] postNotificationName:downloadFileRefreshNotification object:_curDownloadFileModel];
    
}

//检查是否需要重新下载
- (void)checkReDownloadFileFun
{
    if(!_curDownloadFileModel){
        return;
    }
    
    if(_isSuspendType){
        return;
    }
    
    NSInteger curTime = [iTools getNowTimeStamp];
    
    if(self.taskRenewTime == 0){
        return;
    }
    
    if(curTime - self.taskRenewTime < 10){
        return;
    }
    
    if(![self checkFreeDiskSpaceInBytesIsOK:_curDownloadFileModel.length]){
        mainBlock(^{
            [[iToast makeText:NSLocalizedString(@"phone_space_Insufficient",nil)] show];
        });
        _curDownloadFileModel = nil;
        return;
    }
    
    [[NSNotificationCenter defaultCenter] postNotificationName:downloadFileBeginNotification object:_curDownloadFileModel];
}

- (void)didDownloadAllTaskDoneFun
{
    [[NSNotificationCenter defaultCenter] postNotificationName:downloadFileAllTaskDoneNotification object:nil];
}

- (void)checkHadDownloadTaskWithComplete:(custom_complete_B)complete
{
    [self getDataInDatabaseFun:NO complete:^(NSMutableArray * _Nonnull Arr) {
        mainBlock(^{
            if(!Arr || Arr.count != 3){
                complete(NO);
            }
            else{
                NSArray *firstArr = Arr[0];
                if(firstArr.count >0){
                    complete(YES);
                }
                else{
                    complete(NO);
                }
            }
        });
        
    }];
}
@end
