//
//  ZYJOSSCompat.m
//  ZYJOSS_ios_sdk_new
//
//  Created by zhouzhuo on 9/10/15.
//  Copyright (c) 2015 aliyun.com. All rights reserved.
//

#import "ZYJOSSDefine.h"
#import "ZYJOSSCompat.h"
#import "ZYJOSSBolts.h"
#import "ZYJOSSModel.h"

@implementation ZYJOSSClient (Compat)

- (ZYJOSSTaskHandler *)uploadData:(NSData *)data
               withContentType:(NSString *)contentType
                withObjectMeta:(NSDictionary *)meta
                  toBucketName:(NSString *)bucketName
                   toObjectKey:(NSString *)objectKey
                   onCompleted:(void(^)(BOOL, NSError *))onCompleted
                    onProgress:(void(^)(float progress))onProgress {

    ZYJOSSTaskHandler * bcts = [ZYJOSSCancellationTokenSource cancellationTokenSource];

    [[[ZYJOSSTask taskWithResult:nil] continueWithExecutor:self.ZYJOSSOperationExecutor withSuccessBlock:^id(ZYJOSSTask *task) {
        ZYJOSSPutObjectRequest * put = [ZYJOSSPutObjectRequest new];
        put.bucketName = bucketName;
        put.objectKey = objectKey;
        put.objectMeta = meta;
        put.uploadingData = data;
        put.contentType = contentType;

        put.uploadProgress = ^(int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) {
            if (totalBytesExpectedToSend) {
                onProgress((float)totalBytesSent / totalBytesExpectedToSend);
            }
        };

        [bcts.token registerCancellationObserverWithBlock:^{
            [put cancel];
        }];

        ZYJOSSTask * putTask = [self putObject:put];
        [putTask waitUntilFinished];
        onProgress(1.0f);
        return putTask;
    }] continueWithBlock:^id(ZYJOSSTask *task) {
        if (task.error) {
            onCompleted(NO, task.error);
        } else {
            onCompleted(YES, nil);
        }
        return nil;
    }];
    return bcts;
}

- (ZYJOSSTaskHandler *)downloadToDataFromBucket:(NSString *)bucketName
                                 objectKey:(NSString *)objectKey
                               onCompleted:(void (^)(NSData *, NSError *))onCompleted
                                onProgress:(void (^)(float))onProgress {

    ZYJOSSTaskHandler * bcts = [ZYJOSSCancellationTokenSource cancellationTokenSource];

    [[[ZYJOSSTask taskWithResult:nil] continueWithExecutor:self.ZYJOSSOperationExecutor withBlock:^id(ZYJOSSTask *task) {
        ZYJOSSGetObjectRequest * get = [ZYJOSSGetObjectRequest new];
        get.bucketName = bucketName;
        get.objectKey = objectKey;

        get.downloadProgress = ^(int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) {
            if (totalBytesExpectedToWrite) {
                onProgress((float)totalBytesWritten / totalBytesExpectedToWrite);
            }
        };

        [bcts.token registerCancellationObserverWithBlock:^{
            [get cancel];
        }];

        ZYJOSSTask * getTask = [self getObject:get];
        [getTask waitUntilFinished];
        onProgress(1.0f);
        return getTask;
    }] continueWithBlock:^id(ZYJOSSTask *task) {
        if (task.error) {
            onCompleted(nil, task.error);
        } else {
            ZYJOSSGetObjectResult * result = task.result;
            onCompleted(result.downloadedData, nil);
        }
        return nil;
    }];

    return bcts;
}

- (ZYJOSSTaskHandler *)downloadToFileFromBucket:(NSString *)bucketName
                                 objectKey:(NSString *)objectKey
                                    toFile:(NSString *)filePath
                               onCompleted:(void (^)(BOOL, NSError *))onCompleted
                                onProgress:(void (^)(float))onProgress {

    ZYJOSSTaskHandler * bcts = [ZYJOSSCancellationTokenSource cancellationTokenSource];

    [[[ZYJOSSTask taskWithResult:nil] continueWithExecutor:self.ZYJOSSOperationExecutor withBlock:^id(ZYJOSSTask *task) {
        ZYJOSSGetObjectRequest * get = [ZYJOSSGetObjectRequest new];
        get.bucketName = bucketName;
        get.objectKey = objectKey;
        get.downloadToFileURL = [NSURL fileURLWithPath:filePath];

        get.downloadProgress = ^(int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) {
            if (totalBytesExpectedToWrite) {
                onProgress((float)totalBytesWritten / totalBytesExpectedToWrite);
            }
        };

        [bcts.token registerCancellationObserverWithBlock:^{
            [get cancel];
        }];

        ZYJOSSTask * getTask = [self getObject:get];
        [getTask waitUntilFinished];
        onProgress(1.0f);
        return getTask;
    }] continueWithBlock:^id(ZYJOSSTask *task) {
        if (task.error) {
            onCompleted(NO, task.error);
        } else {
            onCompleted(YES, nil);
        }
        return nil;
    }];
    
    return bcts;
}

- (void)deleteObjectInBucket:(NSString *)bucketName
                   objectKey:(NSString *)objectKey
                 onCompleted:(void (^)(BOOL, NSError *))onCompleted {

    [[[ZYJOSSTask taskWithResult:nil] continueWithExecutor:self.ZYJOSSOperationExecutor withBlock:^id(ZYJOSSTask *task) {
        ZYJOSSDeleteObjectRequest * delete = [ZYJOSSDeleteObjectRequest new];
        delete.bucketName = bucketName;
        delete.objectKey = objectKey;

        ZYJOSSTask * deleteTask = [self deleteObject:delete];
        [deleteTask waitUntilFinished];
        return deleteTask;
    }] continueWithBlock:^id(ZYJOSSTask *task) {
        if (task.error) {
            onCompleted(NO, task.error);
        } else {
            onCompleted(YES, nil);
        }
        return nil;
    }];
}

- (ZYJOSSTaskHandler *)uploadFile:(NSString *)filePath
               withContentType:(NSString *)contentType
                withObjectMeta:(NSDictionary *)meta
                  toBucketName:(NSString *)bucketName
                   toObjectKey:(NSString *)objectKey
                   onCompleted:(void (^)(BOOL, NSError *))onCompleted
                    onProgress:(void (^)(float))onProgress {

    ZYJOSSTaskHandler * bcts = [ZYJOSSCancellationTokenSource cancellationTokenSource];

    [[[ZYJOSSTask taskWithResult:nil] continueWithExecutor:self.ZYJOSSOperationExecutor withSuccessBlock:^id(ZYJOSSTask *task) {
        ZYJOSSPutObjectRequest * put = [ZYJOSSPutObjectRequest new];
        put.bucketName = bucketName;
        put.objectKey = objectKey;
        put.objectMeta = meta;
        put.uploadingFileURL = [NSURL fileURLWithPath:filePath];
        put.contentType = contentType;

        put.uploadProgress = ^(int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) {
            if (totalBytesExpectedToSend) {
                onProgress((float)totalBytesSent / totalBytesExpectedToSend);
            }
        };

        [bcts.token registerCancellationObserverWithBlock:^{
            [put cancel];
        }];

        ZYJOSSTask * putTask = [self putObject:put];
        [putTask waitUntilFinished];
        onProgress(1.0f);
        return putTask;
    }] continueWithBlock:^id(ZYJOSSTask *task) {
        if (task.error) {
            onCompleted(NO, task.error);
        } else {
            onCompleted(YES, nil);
        }
        return nil;
    }];
    return bcts;
}

- (ZYJOSSTaskHandler *)resumableUploadFile:(NSString *)filePath
                        withContentType:(NSString *)contentType
                         withObjectMeta:(NSDictionary *)meta
                           toBucketName:(NSString *)bucketName
                            toObjectKey:(NSString *)objectKey
                            onCompleted:(void(^)(BOOL, NSError *))onComplete
                             onProgress:(void(^)(float progress))onProgress {

    ZYJOSSTaskHandler * bcts = [ZYJOSSCancellationTokenSource cancellationTokenSource];

    [[[ZYJOSSTask taskWithResult:nil] continueWithBlock:^id(ZYJOSSTask *task) {
        NSURL * fileURL = [NSURL fileURLWithPath:filePath];
        NSDate * lastModified;
        NSError * error;
        [fileURL getResourceValue:&lastModified forKey:NSURLContentModificationDateKey error:&error];
        if (error) {
            return [ZYJOSSTask taskWithError:error];
        }
        ZYJOSSResumableUploadRequest * resumableUpload = [ZYJOSSResumableUploadRequest new];
        resumableUpload.bucketName = bucketName;
        resumableUpload.deleteUploadIdOnCancelling = NO;//cancel not delete record file
        resumableUpload.contentType = contentType;
        resumableUpload.completeMetaHeader = meta;
        NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
        resumableUpload.recordDirectoryPath = cachesDir; //default record file path
        resumableUpload.uploadingFileURL = fileURL;
        resumableUpload.objectKey = objectKey;
        resumableUpload.uploadId = task.result;
        resumableUpload.uploadingFileURL = [NSURL fileURLWithPath:filePath];
        __weak ZYJOSSResumableUploadRequest * weakRef = resumableUpload;
        resumableUpload.uploadProgress = ^(int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) {
            onProgress((float)totalBytesSent/totalBytesExpectedToSend);
            if (bcts.token.isCancellationRequested || bcts.isCancellationRequested) {
                [weakRef cancel];
            }
            ZYJOSSLogDebugNoFile(@"%lld %lld %lld", bytesSent, totalBytesSent, totalBytesExpectedToSend);
        };
        return [self resumableUpload:resumableUpload];
    }] continueWithBlock:^id(ZYJOSSTask *task) {
        if (task.cancelled) {
            onComplete(NO, [NSError errorWithDomain:ZYJOSSClientErrorDomain
                                               code:ZYJOSSClientErrorCodeTaskCancelled
                                           userInfo:@{ZYJOSSErrorMessageTOKEN: @"This task is cancelled"}]);
        } else if (task.error) {
            onComplete(NO, task.error);
        } else if (task.faulted) {
            onComplete(NO, [NSError errorWithDomain:ZYJOSSClientErrorDomain
                                               code:ZYJOSSClientErrorCodeExcpetionCatched
                                           userInfo:@{ZYJOSSErrorMessageTOKEN: [NSString stringWithFormat:@"Catch exception - %@", task.exception]}]);
        } else {
            onComplete(YES, nil);
        }
        return nil;
    }];
    return bcts;
}

@end
