//
//  DropboxModel.m
//  PDF Reader
//
//  Created by HuFeng on 13-3-27.
//  Copyright (c) 2013年 zhangjie. All rights reserved.
// __MAC_10_9

#import "DropboxModel.h"
//#import "Constant.h"
//#import "KMMember+Receipt.h"
//#import "KMPurchaseCompareTool.h"
//#import "PDFReaderAppDelegate.h"

#if __MAC_OS_X_VERSION_MAX_ALLOWED > __MAC_10_9
#import <ObjectiveDropboxOfficial/ObjectiveDropboxOfficial.h>
#endif

#define UserNameKey       @"GetUserName"
#define FileSyncDateKey   @"FileSyncDate"
#define UserEmailKey       @"GetEmailName"

@interface DropboxModel ()
@property(nonatomic, copy) NSString *appKey;
@property(nonatomic, copy) NSString *appSecret;
@property(nonatomic, copy) NSString *root;

#if __MAC_OS_X_VERSION_MAX_ALLOWED > __MAC_10_9
@property (nonatomic,retain) DBUploadTask *uploadTask;
#endif

@end

@implementation DropboxModel
@synthesize objectDelegate;
@synthesize appKey           = _appKey;
@synthesize appSecret        = _appSecret;
@synthesize root             = _root;
@synthesize filePathArray     = _filePathArray;
@synthesize currentUploadPath = _currentUploadPath;
@synthesize userName          = _userName;
@synthesize syncDate          = _syncDate;

+ (DropboxModel *)shared {
    static DropboxModel *sharedModel = nil;
    static dispatch_once_t predicate;
    dispatch_once(&predicate, ^{
        sharedModel = [[DropboxModel alloc] init];
    });
    return sharedModel;
}

- (id)init {
    self = [super init];
    if (self) {
        // 设置 Dropbox 的app参数,由彦忠管理,
#if VERSION_PRO
        self.appKey = @"amipzwtlg9lrwyl";
#else
        self.appKey = @"jxjlqfm1cfp2mjj";
#endif

        NSString *registeredUrlToHandle = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleURLTypes"][0][@"CFBundleURLSchemes"][0];
        if (!self.appKey ||
            [registeredUrlToHandle rangeOfString:@"<"].location != NSNotFound) {
            NSString *message = @"You need to set `appKey` variable in `AppDelegate.m`, as well as add to `Info.plist`, before you can use DBRoulette.";
            NSLog(@"%@", message);
            NSLog(@"Terminating...");
            exit(1);
        }

        self.userName = [[NSUserDefaults standardUserDefaults] objectForKey:UserNameKey];
        self.syncDate = [[NSUserDefaults standardUserDefaults] objectForKey:FileSyncDateKey];
        self.userEmail = [[NSUserDefaults standardUserDefaults] objectForKey:UserEmailKey];
    }
    return self;
}

#pragma mark -
#pragma mark ===== User Login =====
- (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
{
    NSURL *url = [NSURL URLWithString:[[event paramDescriptorForKeyword:keyDirectObject] stringValue]];
//     [DBClientsManager handleRedirectURL:url completion:^(DBOAuthResult * _Nullable authResult) {
//        if (authResult != nil) {
//            if ([authResult isSuccess]) {
//                NSLog(@"Success! User is logged into Dropbox.");
//                if( [self isLinked]){
//                    [self loadAccountInfomation];
//                    
//                    if (nil != self.filePathArray) {
//                        [self uploadFileToServer];
//                    }
//                }
//                
//            } else if ([authResult isCancel]) {
//                if ([objectDelegate respondsToSelector:@selector(cancelUpLoadProgressBar)]) {
//                    [objectDelegate cancelUpLoadProgressBar];
//                }
//            } else if ([authResult isError]) {
//                if ([objectDelegate respondsToSelector:@selector(cancelUpLoadProgressBar)]) {
//                    [objectDelegate cancelUpLoadProgressBar];
//                }
//                
//                NSAlert *alert = [[NSAlert alloc] init];
//                [alert setAlertStyle:NSAlertStyleCritical];
//                [alert setMessageText:authResult.errorDescription];
//                [alert runModal];
//                NSLog(@"Error: %@", authResult);
//            }
//        }
//    }];
}

- (void)handleAuthResult:(DBOAuthResult *)authResult {
    if (authResult != nil) {
        if ([authResult isSuccess]) {
            NSLog(@"Success! User is logged into Dropbox.");
            if( [self isLinked]){
                [self loadAccountInfomation];
                
                if (nil != self.filePathArray) {
                    [self uploadFileToServer];
                }
            }
            
        } else if ([authResult isCancel]) {
            if ([objectDelegate respondsToSelector:@selector(cancelUpLoadProgressBar)]) {
                [objectDelegate cancelUpLoadProgressBar];
            }
        } else if ([authResult isError]) {
            if ([objectDelegate respondsToSelector:@selector(cancelUpLoadProgressBar)]) {
                [objectDelegate cancelUpLoadProgressBar];
            }
            
            NSAlert *alert = [[NSAlert alloc] init];
            [alert setAlertStyle:NSAlertStyleCritical];
            [alert setMessageText:authResult.errorDescription];
            [alert runModal];
            NSLog(@"Error: %@", authResult);
        }
    }
}

- (void)loadAccountInfomation
{
    DBUserClient *client = [DBClientsManager authorizedClient];
    [[client.usersRoutes getCurrentAccount] setResponseBlock:^(DBUSERSFullAccount * _Nullable result, DBNilObject * _Nullable routeError, DBRequestError * _Nullable networkError) {
        
        if (![_userName isEqualToString:result.name.givenName]) {
            self.userName = result.name.givenName;
            [[NSUserDefaults standardUserDefaults] setObject:self.userName forKey:UserNameKey];
            [[NSUserDefaults standardUserDefaults] synchronize];
            
        }
        self.userEmail = result.email;
        [[NSUserDefaults standardUserDefaults] setObject:self.userEmail forKey:UserEmailKey];
        [[NSNotificationCenter defaultCenter] postNotificationName:kUpdateUserName object:self.userName];
        
    }];
}

#pragma mark -
#pragma mark ===== authenticate =====
- (void)linkServer
{
    [DBClientsManager authorizeFromControllerDesktop:[NSWorkspace sharedWorkspace]
                                          controller:nil
                                             openURL:^(NSURL *url){
        [[NSWorkspace sharedWorkspace] openURL:url];
    }];
}

- (void)unlinkAll
{
    if ([DBClientsManager authorizedClient])
    {
        [DBClientsManager unlinkAndResetClients];
        self.userName = NSLocalizedString(@"Invalid Username",nil);
        [[NSUserDefaults standardUserDefaults] setObject:self.userName forKey:UserNameKey];
        [[NSUserDefaults standardUserDefaults] synchronize];
        [[NSNotificationCenter defaultCenter] postNotificationName:kUpdateUserName object:self.userName];
    }
}

- (BOOL)isLinked
{
    return ([DBClientsManager authorizedClient] ? YES : NO);
}

- (void)getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
{
    // This gets called when the user clicks Show "App name". You don't need to do anything for Dropbox here
}

#define FreeVersion_UploadInformation @"FreeVersionUploadInformation"
#define FreeVersion_UploadInformation_UploadDate @"UploadDate"
#define FreeVersion_UploadInformation_FileCount @"UploadFileCount"
- (void)updateNumberOfUploadFile
{
    if ([[NSUserDefaults standardUserDefaults] objectForKey:FreeVersion_UploadInformation]) {
        if ([self numberOfUploadFile] != 0) {
            NSDictionary *dic = [[NSUserDefaults standardUserDefaults] objectForKey:FreeVersion_UploadInformation];
            NSNumber *number = [dic objectForKey:FreeVersion_UploadInformation_FileCount];
            NSInteger count = [number integerValue];
            count++;
            NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                        [NSDate date],FreeVersion_UploadInformation_UploadDate,
                                        [NSNumber numberWithInteger:count],FreeVersion_UploadInformation_FileCount,nil];
            [[NSUserDefaults standardUserDefaults] setObject:dictionary forKey:FreeVersion_UploadInformation];
            [[NSUserDefaults standardUserDefaults] synchronize];
            return;
        }
    }
    NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:
                         [NSDate date],FreeVersion_UploadInformation_UploadDate,
                         [NSNumber numberWithInteger:1],FreeVersion_UploadInformation_FileCount,nil];
    [[NSUserDefaults standardUserDefaults] setObject:dic forKey:FreeVersion_UploadInformation];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

- (NSInteger)numberOfUploadFile
{
    NSDateComponents *ccomps = [[NSCalendar currentCalendar] components:(NSYearCalendarUnit | NSMonthCalendarUnit |NSDayCalendarUnit)
                                                               fromDate:[NSDate date]];
    NSInteger cyear = [ccomps year];
    NSInteger cmonth = [ccomps month];
    NSInteger cday = [ccomps day];
    if ([[NSUserDefaults standardUserDefaults] objectForKey:FreeVersion_UploadInformation]) {
        NSDictionary *dic = [[NSUserDefaults standardUserDefaults] objectForKey:FreeVersion_UploadInformation];
        
        NSDate *date = [dic objectForKey:FreeVersion_UploadInformation_UploadDate];
        NSNumber *number = [dic objectForKey:FreeVersion_UploadInformation_FileCount];
        
        if (date) {
            NSDateComponents *comps = [[NSCalendar currentCalendar] components:(NSYearCalendarUnit | NSMonthCalendarUnit |NSDayCalendarUnit)
                                                                      fromDate:date];
            NSInteger year = [comps year];
            NSInteger month = [comps month];
            NSInteger day = [comps day];
            if (year == cyear &&
                month == cmonth &&
                day == cday) {
                return [number integerValue];
            } else {
                return 0;
            }
        } else {
            return 0;
        }
    }
    return 0;
}

#pragma mark -
#pragma mark ===== UPload files =====
- (BOOL)uploadFile:(NSArray *)filePathArray
{
    self.filePathArray = filePathArray;
//    if (![IAPProductsManager defaultManager].isAvailableAllFunction) {
        //免費版當天只能限制dropbox 10個檔案同步
        NSUInteger count = [self numberOfUploadFile];
//        if (10 <= count) {
//            [KMPurchaseCompareTool showPurchaseCompareWindowController];
//            return NO;
//        } else if (count<10 && count > 0) {
            if (self.filePathArray.count > (10-count)) {
                self.filePathArray = [filePathArray subarrayWithRange:NSMakeRange(0, 10-count)];
            }
//        }
//    }
    if ([self isLinked]) {
        [self uploadFileToServer];
    } else {
        if ([objectDelegate respondsToSelector:@selector(updateUploadProgressBar:withMessage:leftFilesString:)]) {
            [objectDelegate updateUploadProgressBar:0
                                        withMessage:NSLocalizedString(@"Authenticating...", nil)
                                    leftFilesString:nil];
        }
        [self linkServer];
    }
    return YES;
}

- (void)uploadFileToServer
{
    _currentUploadPath = [_filePathArray objectAtIndex:0];
    [self newUploatFile];
}

- (void)newUploatFile
{
    [self updateNumberOfUploadFile];
    
    NSData *fileData = [[NSData alloc] initWithContentsOfURL:[NSURL fileURLWithPath:_currentUploadPath]];
    NSString * path = [NSString stringWithFormat:@"/%@",[_currentUploadPath lastPathComponent]];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        DBUserClient * client = [DBClientsManager authorizedClient];
        self.uploadTask = [client.filesRoutes uploadData:path inputData:fileData];
        
        [[self.uploadTask setResponseBlock:^(DBFILESFileMetadata *result, DBFILESUploadError *routeError, DBRequestError *networkError) {
            if (result) {
                NSLog(@"---上传成功");
                self.syncDate = [self fileSyncDateStr];
                [[NSUserDefaults standardUserDefaults] setObject:self.syncDate forKey:FileSyncDateKey];
                [[NSUserDefaults standardUserDefaults] synchronize];
                
                NSInteger cnt = [_filePathArray count];
                NSInteger index = [_filePathArray indexOfObject:_currentUploadPath];
                if (1 == _progressValue && index < cnt - 1) {
                    _currentUploadPath = [_filePathArray objectAtIndex:index + 1];
                    [self newUploatFile];
                } else {
                    self.filePathArray = nil;
                }
            } else {
                NSLog(@"---上传失败");
                [self newUploadFileState:networkError.statusCode.integerValue];
            }
        }] setProgressBlock:^(int64_t bytesUploaded, int64_t totalBytesUploaded, int64_t totalBytesExpectedToUploaded) {
            NSInteger cnt = [_filePathArray count];
            NSInteger index = [_filePathArray indexOfObject:_currentUploadPath];
            _progressValue = totalBytesUploaded/(CGFloat)(totalBytesExpectedToUploaded);
            float totalProgress = (index + _progressValue)/cnt;
            if ([objectDelegate respondsToSelector:@selector(updateUploadProgressBar:withMessage:leftFilesString:)]) {
                NSString * contenxtString = nil;
                if (self.filePathArray.count > 1) {
                    contenxtString = [NSString stringWithFormat:NSLocalizedString(@"%ld files left", nil),cnt - index];
                } else {
                    contenxtString = [NSString stringWithFormat:NSLocalizedString(@"%ld file left", nil),cnt - index];
                }
                [objectDelegate updateUploadProgressBar:totalProgress
                                            withMessage:NSLocalizedString(@"Uploading...", nil)
                                        leftFilesString:contenxtString];
            }
        }];
    });
}

- (void)newUploadFileState:(NSInteger)code
{
    NSLog(@"---上传失败");
    self.filePathArray = nil;
    
    if ([objectDelegate respondsToSelector:@selector(cancelUpLoadProgressBar)]) {
        [objectDelegate cancelUpLoadProgressBar];
    }
    
    NSAlert *alert = [[NSAlert alloc] init];
    [alert setAlertStyle:NSAlertStyleCritical];
    
    NSString *tStrMessage = NSLocalizedString(@"Server Error", nil);
    
    switch (code) {
        case 400:
        {
            NSLog(@"Bad input parameter.");
            tStrMessage = NSLocalizedString(@"Upload Failed!", nil);
        }
            break;
        case 401:
            NSLog(@"Bad or expired token.");
            tStrMessage = NSLocalizedString(@"Authentication Failed!", nil);
            break;
        case 403:
            NSLog(@"Bad OAuth request.");
            tStrMessage = NSLocalizedString(@"Authentication Failed!", nil);
            break;
        case 404:
            NSLog(@"The file or folder is not found at the specified path.");
            tStrMessage = NSLocalizedString(@"Upload Failed!", nil);
            break;
        case 405:
            NSLog(@"Request method not expected (generally should be GET or POST).");
            tStrMessage = NSLocalizedString(@"Upload Failed!", nil);
            break;
        case 409:
            NSLog(@"Unlike many other error codes, it doesn’t have any specific meaning in the HTTP spec.");
            tStrMessage = NSLocalizedString(@"Unlike many other error codes, it doesn’t have any specific meaning in the HTTP spec.", nil);
            break;
        case 503:
            NSLog(@"Your app is making too many requests and is being rate limited.");
            tStrMessage = NSLocalizedString(@"Upload Failed!", nil);
            break;
        case 507:
            NSLog(@"User is over Dropbox storage quota.");
            tStrMessage = NSLocalizedString(@"Upload Failed!", nil);
            break;
        default:
            tStrMessage = NSLocalizedString(@"Server Error", nil);
            break;
    }
    
    [alert setMessageText:tStrMessage];
    
    [alert runModal];
}

- (void)cancleUploadFile
{
    self.filePathArray = nil;
    if ([self isLinked]) {
        [self.uploadTask cancel];
    }
}

#pragma mark -

- (NSString *)fileSyncDateStr
{
    NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateStyle:(kCFDateFormatterShortStyle)];
    [dateFormatter setTimeStyle:(kCFDateFormatterShortStyle)];
    return [dateFormatter stringFromDate:[NSDate date]];
}

@end