//
//  OSSManager.m
//  AliyunOSSSDK-iOS-Example
//
//  Created by huaixu on 2018/10/23.
//  Copyright © 2018 aliyun. All rights reserved.
//

#import "OSSManager.h"
#import "OssNetApi.h"
#import <AliyunOSSiOS/OSSService.h>
#import "ChatsStore.h"
#import "GDBManager.h"
#import "GWebSocket.h"

// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1（杭州）为例，Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
#define endpoint @"https://oss-ap-southeast-1.aliyuncs.com"//生产服务器


@interface OSSManager ()

@property (nonatomic, strong) OSSPutObjectRequest *normalUploadRequest;

@property (nonatomic, strong) OSSGetObjectRequest *normalDloadRequest;

@property (nonatomic, strong) NSDateFormatter *formatter;
@property (nonatomic, copy) NSString *month;
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSNumber *> *taskDict;
@end


@implementation OSSManager

+ (instancetype)sharedManager {
    static OSSManager *_manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _manager = [[OSSManager alloc] init];
    });
    
    return _manager;
}

- (instancetype)init {
    if (self = [super init]) {
        _uploadTanck = [NSMutableArray new];
        _taskDict = [NSMutableDictionary dictionary];
    }
    return self;
}


-(void)getOSSInfo:(void (^_Nullable)(bool))success{
    if (!_uploadTanck) {
        _uploadTanck = [NSMutableArray new];
    }
    
    [OssNetApi getOSSInfo:nil succ:^(int code, NSDictionary * res) {
        NSLog(@"res:%@",res);
        NSString *codeV =res[@"code"];
        if(codeV.intValue==200){
            self.OSSInfo = res[@"data"];
            if(self.OSSInfo){
                [UDManager.shareInstance setDDManager:self.OSSInfo key:nkOSSinfo];
                success(true);
            }
        }
        else{
            success(false);
        }
    } fail:^(NSError * _Nonnull error) {
        success(false);
    }];
}

-(void)initmyAliyunOSS{
    if(self.OSSInfo){
        // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1（杭州）为例，Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
        //NSString *endpoint = @"https://oss-ap-southeast-1.aliyuncs.com";
   
        // 旧版本图片服务的endpoint
//        NSString *oldimgendpoint =  @"http://img-ap-southeast-1.aliyuncs.com";
        // 从STS服务获取的临时访问密钥（AccessKey ID和AccessKey Secret）。
        NSString *accessKeyId = self.OSSInfo[@"accessKeyId"];
        NSString *accessKeySecret = self.OSSInfo[@"accessKeySecret"];
        // 从STS服务获取的安全令牌（SecurityToken）。
        NSString *securityToken = self.OSSInfo[@"securityToken"];
//        NSString *expiration = self.OSSInfo[@"expiration"];
       
        
        id<OSSCredentialProvider> credentialProvider = [[OSSStsTokenCredentialProvider alloc] initWithAccessKeyId:accessKeyId secretKeyId:accessKeySecret securityToken:securityToken];
        OSSClientConfiguration *cfg = [[OSSClientConfiguration alloc] init];
        cfg.maxRetryCount = 5;
        cfg.timeoutIntervalForRequest = 15;
        cfg.isHttpdnsEnable = NO;
        cfg.crc64Verifiable = YES;
        
        OSSClient *defaultClient = [[OSSClient alloc] initWithEndpoint:endpoint credentialProvider:credentialProvider clientConfiguration:cfg];
        [OSSManager sharedManager].defaultClient = defaultClient;
        
        NSDate *now = [NSDate date];
        NSTimeInterval trt = [now timeIntervalSince1970];
        self.initIme = trt;
       
        //旧的图片服务
//        OSSClient *defaultImgClient = [[OSSClient alloc] initWithEndpoint:oldimgendpoint credentialProvider:credentialProvider clientConfiguration:cfg];
//        [OSSManager sharedManager].imageClient = defaultImgClient;
    }
}


//普通上传
- (void)asyncPutFile:(NSString *)objectKey localFilePath:(NSString *)filePath thrid:(NSString *)strtime{
    
    if([self chectToken]){
        if([OSSManager sharedManager].defaultClient==nil){
            [self getOSSInfo:^(bool code){
                if(code){
                    [self initmyAliyunOSS];
                    [self prasyncPutFile:objectKey localFilePath:filePath thrid:strtime];
                }
                else{
                    [MBProgressHUD showWithText:@"OSS文件服务初始化失败！請重試"];
                }
            }];
        }
        else{
            [self prasyncPutFile:objectKey localFilePath:filePath thrid:strtime];
        }
    }
    else{
        [self getOSSInfo:^(bool code){
            if(code){
                [self initmyAliyunOSS];
                [self prasyncPutFile:objectKey localFilePath:filePath thrid:strtime];
            }
            else{
                [MBProgressHUD showWithText:@"OSS文件服务初始化失败！請重試"];
            }
        }];
    }
}


-(void)prasyncPutFile:(NSString *)objectKey localFilePath:(NSString *)filePath thrid:(NSString *)strtime{
    
    if (![objectKey oss_isNotEmpty]) {
        if(self.delegate){
            NSDictionary *dic=@{
                @"state":@"3",
                @"pcent":@"",
                @"thrid":strtime
            };
            [self.delegate stateChange:dic];
        }
        return;
    }
    
    NSLog(@"objectKey:%@",objectKey);
    _normalUploadRequest = [OSSPutObjectRequest new];
    _normalUploadRequest.bucketName = self.OSSInfo[@"bucket"];
    _normalUploadRequest.objectKey = [self formatObjectKeyWith:objectKey];
    _normalUploadRequest.uploadingFileURL = [NSURL fileURLWithPath:filePath];
    _normalUploadRequest.isAuthenticationRequired = YES;
    weakSelf(self);
    _normalUploadRequest.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
        CGFloat progress = 1.f * totalByteSent / totalBytesExpectedToSend;
//        NSLog(@"上传文件进度: %f", progress);
        NSInteger pcent =progress*100;
        if(weakself.delegate){
            NSDictionary *dic=@{
                @"state":@"1",
                @"pcent":[NSString stringWithFormat:@"%ld",(long)pcent],
                @"thrid":strtime
            };
            [weakself.delegate stateChange:dic];
        }
        
    };
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        OSSTask * task = [[OSSManager sharedManager].defaultClient putObject:self->_normalUploadRequest];
        [task continueWithBlock:^id(OSSTask *task) {
            dispatch_async(dispatch_get_main_queue(), ^{
                if (task.error) {
                    [self updataFileMsg:strtime state:@"1"];
                    if(self.delegate){
                        NSDictionary *dic=@{
                            @"state":@"3",
                            @"pcent":@"",
                            @"thrid":strtime
                        };
                        [self.delegate stateChange:dic];
                    }
                } else {
                    NSLog(@"上传文件完成");
                    [self updataFileMsg:strtime state:@"2"];
                    if(self.delegate){
                        NSDictionary *dic=@{
                            @"state":@"2",
                            @"pcent":@"",
                            @"thrid":strtime
                        };
                        [self.delegate stateChange:dic];
                    }
                }
            });
            
            return nil;
        }];
    });
}


//断点续传
- (void)asyncResumableUploadFile:(NSString *)objectKey localFilePath:(NSString *)filePath thrid:(NSString *)strtime{
    
    
    if([self chectToken]){
        if([OSSManager sharedManager].defaultClient==nil){
            [self getOSSInfo:^(bool code){
                if(code){
                    [self initmyAliyunOSS];
                    [self PrasyncResumableUploadFile:objectKey localFilePath:filePath thrid:strtime];
                }
                else{
                    [MBProgressHUD showWithText:@"OSS文件服务初始化失败！請重試"];
                }
            }];
        }
        else{
            [self PrasyncResumableUploadFile:objectKey localFilePath:filePath thrid:strtime];
        }
    }
    else{
        [self getOSSInfo:^(bool code){
            if(code){
                [self initmyAliyunOSS];
                [self PrasyncResumableUploadFile:objectKey localFilePath:filePath thrid:strtime];
            }
            else{
                [MBProgressHUD showWithText:@"OSS文件服务初始化失败！請重試"];
            }
        }];
    }
    
    
}


-(void)PrasyncResumableUploadFile:(NSString *)objectKey localFilePath:(NSString *)filePath thrid:(NSString *)strtime{
    
    NSLog(@"PrasyncResumableUploadFile objectKey: %@ filePath: %@", objectKey, filePath);
    
    NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
    NSString *fileName = [NSURL fileURLWithPath:filePath].lastPathComponent;
    NSString *path = [documentsDirectoryURL URLByAppendingPathComponent:fileName].path;
    if (![[NSFileManager defaultManager] fileExistsAtPath:path]){
        NSLog(@"PrasyncResumableUploadFile error: %@", path);
        return;
    }
    NSString *fileKey = [self fileMessageKeyWith:strtime];
    // 获取UploadId上传文件。
    OSSResumableUploadRequest * resumableUpload = [OSSResumableUploadRequest new];
    resumableUpload.bucketName = self.OSSInfo[@"bucket"];
    // objectKey等同于objectName，表示断点上传文件到OSS时需要指定包含文件后缀在内的完整路径，例如abc/efg/123.jpg
    resumableUpload.objectKey = [self formatObjectKeyWith:objectKey];
    resumableUpload.partSize = 1024 * 1024;
    resumableUpload.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {
//        NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);
        CGFloat progress = 1.f * totalByteSent / totalBytesExpectedToSend;
//        NSLog(@"上传文件进度: %f", progress);
        NSInteger pcent =progress*100;
        
        if(self.delegate){
            NSDictionary *dic=@{
                @"state":@"1",
                @"pcent":[NSString stringWithFormat:@"%ld",(long)pcent],
                @"thrid":strtime
            };
            [self.delegate stateChange:dic];
        }
        
        dispatch_main_async_safe(^{
            [self.taskDict setValue:@(pcent) forKey:fileKey];
        })
        
//        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//            prgress(pcent,strtime);
//        });
    };
    NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
    // 设置断点记录保存路径。
    resumableUpload.recordDirectoryPath = cachesDir;
    // 将参数deleteUploadIdOnCancelling设置为NO，表示不删除断点记录文件，上传失败后将从断点记录处继续上传直到文件上传完成。如果不设置此参数，即保留默认值YES，表示删除断点记录文件，下次再上传同一文件时则重新上传。
    resumableUpload.deleteUploadIdOnCancelling = NO;

    resumableUpload.uploadingFileURL = [NSURL URLWithString:path];
    OSSTask * resumeTask = [[OSSManager sharedManager].defaultClient resumableUpload:resumableUpload];
    [self addUploadTanckobj:resumeTask thrid:strtime];
    [resumeTask continueWithBlock:^id(OSSTask *task) {
        if (task.error) {
            NSLog(@"error: %@", task.error);
            if ([task.error.domain isEqualToString:OSSClientErrorDomain] && task.error.code == OSSClientErrorCodeCannotResumeUpload) {
                // 此任务无法续传，需获取新的uploadId重新上传。
            }
            dispatch_main_async_safe(^{
                [[NSUserDefaults standardUserDefaults] setValue:@(-1) forKey:fileKey];
            })
            [self updataFileMsg:strtime state:@"3"];
//            if(self.delegate){
//                NSDictionary *dic=@{
//                    @"state":@"3",
//                    @"pcent":@"",
//                    @"thrid":strtime
//                };
//                [self.delegate stateChange:dic];
//            }
        } else {
            NSLog(@"Upload file success");
            dispatch_main_async_safe(^{
                [[NSUserDefaults standardUserDefaults] setValue:@(100) forKey:fileKey];
            })
            [self updataFileMsg:strtime state:@"2"];
//            if(self.delegate){
//                NSDictionary *dic=@{
//                    @"state":@"2",
//                    @"pcent":@"",
//                    @"thrid":strtime
//                };
//                [self.delegate stateChange:dic];
//            }
        }
        return nil;
    }];
//    [resumeTask waitUntilFinished];
//    [resumableUpload cancel];
}





-(void)addUploadTanckobj:(OSSTask *)task thrid:(NSString *)thrid{
    NSDictionary *item = @{
        @"task":task,
        @"thrid":thrid
    };
    [_uploadTanck addObject:item];
}



-(BOOL)isuploadTanck:(NSString *)thrid{
//    NSLog(@"stopUploadTanck-------------2");
    if(_uploadTanck.count>0){
        for (NSDictionary *item in _uploadTanck) {
            NSString *th = item[@"thrid"];
            NSLog(@"stopUploadTanck-------------3");
            if([th isEqualToString:thrid]){
                NSLog(@"stopUploadTanck-------------4");
                return true;
            }
        }
    }
    return false;
}

-(void)removeUploadTanckobj:(NSString *)thrid{
    if(_uploadTanck.count>0){
        for (NSDictionary *item in _uploadTanck) {
            NSString *th = item[@"thrid"];
            if([th isEqualToString:thrid]){
                [_uploadTanck removeObject:item];
                return;
            }
        }
    }
}

-(void)stopUploadTanck:(NSString *)thrid{
    NSLog(@"stopUploadTanck-------------2");
    if(_uploadTanck.count>0){
        for (NSDictionary *item in _uploadTanck) {
            NSString *th = item[@"thrid"];
            NSLog(@"stopUploadTanck-------------3");
            if([th isEqualToString:thrid]){
                OSSTask *task = item[@"task"];
                NSLog(@"stopUploadTanck-------------4");
                //[task cancel];取消传输
              
                return;
            }
        }
    }
}


-(void)updataFileMsg:(NSString *)thrid state:(NSString *)state{
    
    [GDBManager.shareInstance selectLocalmsgWithLocaltime:thrid succ:^(NSArray * _Nullable array) {
        NSLog(@"selectLocalmsgWithLocaltime:%@",array);
        
        if(array){
            if(array.count>0){
                NSDictionary *msg =array[0];
                NSString *msgtype = msg[@"messageType"];
                
                if (([msgtype isEqualToString:MessageType_Del]||[msgtype isEqualToString:MessageType_CallBack2])) {
                    return;
                }
                
                NSDictionary *extend=msg[@"extend"];
                NSMutableDictionary *mextend = [extend mutableCopy];
                NSMutableDictionary *mmsg = [msg mutableCopy];
                
                if([state isEqualToString:@"2"]){
                    NSString *localPath =extend[@"localurl"];
                    NSURL *loaclUrl = [NSURL URLWithString:localPath];
                    NSString *url = [self fullUploadURLByAppendPath:loaclUrl.lastPathComponent];
                    [mextend setObject:url forKey:@"url"];
                    [mextend setObject:[NSNumber numberWithInt:0] forKey:@"fileError"];
                    [mmsg setObject:mextend forKey:@"extend"];
                    [mmsg setObject:@"" forKey:@"id"];
                }
                else if([state isEqualToString:@"3"]){
                    [mextend setObject:@"" forKey:@"url"];
//                    [mextend setObject:@"" forKey:@"fileName"];
                    [mextend setObject:[NSNumber numberWithInt:1] forKey:@"fileError"];
                    
                    [mmsg setObject:mextend forKey:@"extend"];
                    [mmsg setObject:@"" forKey:@"id"];
                    [ChatsStore.shareInstance reciveMsg:mmsg];
                    return;
                }
                
                
                NSDictionary *sendInfo = @{
                    @"code":@"2",
                    @"message":mmsg,
                };
                NSError *error;
                NSData *jsonData = [NSJSONSerialization dataWithJSONObject:sendInfo options:0 error:&error];
                if (!jsonData) {
                    NSLog(@"Got an error: %@", error);
                } else {
                    NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
//                    NSLog(@"%@", jsonString);
                    NSLog(@"----发送文件消息2----");
                    [GWebSocket.shareInstance sendMsg:jsonString];
                }
                
            }
        }
    } fail:^(NSString * _Nullable error) {
        ;
    }];
}


-(BOOL)chectToken{
    
    if(self.initIme>0){
        NSDate *now = [NSDate date];
        NSTimeInterval trt = [now timeIntervalSince1970];
        NSInteger time = trt;
        time =time-self.initIme;
        NSLog(@"chectToken------:%ld",(long)time);
        if(time>2000){
            return false;
        }
        else{
            return true;
        }
    }
    else{
        return false;
    }
    
    return false;
}

- (NSString *)fullUploadURLByAppendPath:(NSString *)path {
    return [NSString stringWithFormat:@"http://oss.abtim-my.com/%@/%@", self.month, path];
}

- (NSDateFormatter *)formatter {
    if (!_formatter) {
        _formatter = [[NSDateFormatter alloc] init];
        [_formatter setDateFormat:@"yyyy-MM"]; // 设置你想要的日期格式
    }
    return _formatter;
}

- (NSString *)month {
    if (!_month) {
        _month = [self.formatter stringFromDate:[NSDate date]];
    }
    return _month;
}

- (NSString *)formatObjectKeyWith:(NSString *)objectKey {
    return [NSString stringWithFormat:@"%@/%@", self.month, objectKey];;
}

- (void)applicationWillTerminate {
    NSLog(@"applicationWillTerminate: %@", self.taskDict);
    for (NSString *key in self.taskDict.allKeys) {
        NSInteger progress = [self.taskDict[key] integerValue];
        if (progress < 100) {
            [[NSUserDefaults standardUserDefaults] setValue:@(-1) forKey:key];
        }
    }
}

- (NSString *)fileMessageKeyWith:(NSString *)strtime {
    return [NSString stringWithFormat:@"k_oss_file_%@", strtime];
}

@end
