//
//  OperationDropbox.m
//  tuber
//
//  Created by ドラッサル 亜嵐 on 2017/06/06.
//  Copyright © 2017年 ドラッサル 亜嵐. All rights reserved.
//

#import "OperationDropbox.h"
#import <DropboxSDK/DropboxSDK.h>
#import <CoreGraphics/CGBase.h>

@interface OperationDropbox () <DBSessionDelegate, DBNetworkRequestDelegate, DBRestClientDelegate> {
    NSLock* _lock;
    DBRestClient* restClient;
}


@end

@implementation OperationDropbox

- (void)initFirst {
    NSLog(@"[OperationDropbox] initFirst");

    // Set these variables before launching the app
    NSString* appKey = DROPBOX_APPKEY;
    NSString* appSecret = DROPBOX_APPSECRET;
    NSString *root = kDBRootAppFolder; // Should be set to either kDBRootAppFolder or kDBRootDropbox
    // You can determine if you have App folder access or Full Dropbox along with your consumer key/secret
    // from https://dropbox.com/developers/apps
    
    // Look below where the DBSession is created to understand how to use DBSession in your app
    
    NSString* errorMsg = nil;
    if ([appKey rangeOfCharacterFromSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]].location != NSNotFound) {
        errorMsg = @"Make sure you set the app key correctly in DBRouletteAppDelegate.m";
    } else if ([appSecret rangeOfCharacterFromSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]].location != NSNotFound) {
        errorMsg = @"Make sure you set the app secret correctly in DBRouletteAppDelegate.m";
    } else if ([root length] == 0) {
        errorMsg = @"Set your root to use either App Folder of full Dropbox";
    } else {
        NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"Info" ofType:@"plist"];
        NSData *plistData = [NSData dataWithContentsOfFile:plistPath];
        NSDictionary *loadedPlist =
        [NSPropertyListSerialization
         propertyListFromData:plistData mutabilityOption:0 format:NULL errorDescription:NULL];
        NSString *scheme = [[[[loadedPlist objectForKey:@"CFBundleURLTypes"] objectAtIndex:0] objectForKey:@"CFBundleURLSchemes"] objectAtIndex:0];
        if ([scheme isEqual:@"db-APP_KEY"]) {
            errorMsg = @"Set your URL scheme correctly in DBRoulette-Info.plist";
        }
    }
    
    DBSession* session =
    [[DBSession alloc] initWithAppKey:appKey appSecret:appSecret root:root];
    session.delegate = self; // DBSessionDelegate methods allow you to handle re-authenticating
    [DBSession setSharedSession:session];
    
    [DBRequest setNetworkRequestDelegate:self];
    
    if (errorMsg != nil) {
        [[[UIAlertView alloc]
          //initWithTitle:@"Error Configuring Session" message:errorMsg
          initWithTitle:@"セッション設定のエラーを発生しました。" message:errorMsg
           delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]
         show];
    }
}

- (void)connectToDropbox:(UIViewController*)controller {
    if (![[DBSession sharedSession] isLinked]) {
        [[DBSession sharedSession] linkFromController:controller];
    } else {
        restClient = nil;
        [[DBSession sharedSession] unlinkAll];
        [[[UIAlertView alloc]
          //initWithTitle:@"Account Unlinked!" message:@"Your dropbox account has been unlinked"
          initWithTitle:@"ログアウト" message:@"ログアウトしました！"
          delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]
         show];
        [[NSNotificationCenter defaultCenter]postNotificationName:@"didUnlinkFromDropboxAccountNotification" object:nil];
    }
}

- (void)uploadFile:(NSString*)uploadFilename
        sourcePath:(NSString*)sourcePath
           success:(void(^)(id JSON))successHandler
           failure:(void(^)(NSError *error, id JSON))failureHandler {
    NSString *destinationPath = @"/";
    
    [self.restClient uploadFile:uploadFilename
                         toPath:destinationPath
                  withParentRev:nil
                       fromPath:sourcePath];
}

- (BOOL)isLinked {
    if([[DBSession sharedSession] isLinked]) {
        return true;
    } else {
        return false;
    }
    /*
    NSString* title = [[DBSession sharedSession] isLinked] ? @"Unlink Dropbox" : @"Link Dropbox";
    [linkButton setTitle:title forState:UIControlStateNormal];
    
    self.navigationItem.rightBarButtonItem.enabled = [[DBSession sharedSession] isLinked];
    */
}

#pragma mark DBRestClientDelegate methods

- (void)restClient:(DBRestClient *)client uploadedFile:(NSString *)destPath from:(NSString *)srcPath {
    NSLog(@"[OperationDropbox] uploadedFile %@ %@",destPath, srcPath);
    NSMutableDictionary *uploadStatus = [[NSMutableDictionary alloc] init];
    [uploadStatus setValue:srcPath forKey:@"srcPath"];
    [uploadStatus setValue:destPath forKey:@"destPath"];
    [[NSNotificationCenter defaultCenter]postNotificationName:@"didFinishFromDropboxUploadNotification" object:uploadStatus];
}

- (void)restClient:(DBRestClient *)client uploadFileFailedWithError:(NSError *)error {
    
    //parse the error data for the file name
    NSString *fullErrorData = [NSString stringWithFormat:@"%@",error];
    NSString *answer;
    NSString *message;
    
    if ([fullErrorData containsString:@"FileBase"]) {
        NSRange range = [fullErrorData rangeOfString:@"FileBase"];
        NSRange newRange = {range.location,21};//the known length
        answer = [fullErrorData substringWithRange:newRange];
        
        message = [NSString stringWithFormat: @"The upload for file %@ failed. The remnants will be automatically deleted. You may receive an error message about the deletion - dismiss it.", answer];
    } else {
        message = @"Could not determine the file upload that failed.";
    }
    
    UIAlertView *uploadAlert = [[UIAlertView alloc]initWithTitle:@"Upload Failure" message:message delegate:nil cancelButtonTitle:@"Understood" otherButtonTitles: nil];
    
    //[uploadAlert show];
    
    //Add code to clear any remnants
    
}//restClient:uploadFileFailedWithError

#pragma mark -
#pragma mark DBSessionDelegate methods

- (void)sessionDidReceiveAuthorizationFailure:(DBSession*)session userId:(NSString *)userId {
    relinkUserId = userId;
    [[[UIAlertView alloc]
      //initWithTitle:@"Dropbox Session Ended" message:@"Do you want to relink?" delegate:self
      initWithTitle:@"Dropboxセッションが終了" message:@"再ログインしますか?" delegate:self
      //cancelButtonTitle:@"Cancel" otherButtonTitles:@"Relink", nil]
      cancelButtonTitle:@"キャンセル" otherButtonTitles:@"ログイン", nil]
     show];
}


#pragma mark -
#pragma mark UIAlertViewDelegate methods

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)index {
    if (index != alertView.cancelButtonIndex) {
        if(self.rootViewController) {
            restClient = nil;
            [[DBSession sharedSession] linkUserId:relinkUserId fromController:self.rootViewController];
        }
        NSLog(@"[[DBSession sharedSession] linkUserId:relinkUserId fromController:rootViewController]");
    }
    relinkUserId = nil;
}


#pragma mark -
#pragma mark DBNetworkRequestDelegate methods

static int outstandingRequests;

- (void)networkRequestStarted {
    outstandingRequests++;
    if (outstandingRequests == 1) {
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
    }
}

- (void)networkRequestStopped {
    outstandingRequests--;
    if (outstandingRequests == 0) {
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    }
}


# pragma mark - Singleton pattern

static OperationDropbox *_sharedInstance;

- (instancetype)init {
    @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"[Operation] Use 'sharedInstance' instead of 'init' as this class is singleton." userInfo:nil];
}

+ (instancetype)sharedInstance {
    @synchronized(self) {
        if (_sharedInstance == nil) {
            (void) [[self alloc] initPrivate]; // ここでは代入していない
        }
    }
    return _sharedInstance;
}

- (instancetype)initPrivate {
    self = [super init];
    if (self) {
        // 初期処理
        _lock = [[NSLock alloc] init];
        [self initFirst];
    }
    return self;
}

+ (id)allocWithZone:(NSZone *)zone {
    @synchronized(self) {
        if (_sharedInstance == nil) {
            _sharedInstance = [super allocWithZone:zone];
            return _sharedInstance;  // 最初の割り当てで代入し、返す
        }
    }
    return nil;
}

- (id)copyWithZone:(NSZone *)zone {
    return self;
}

- (DBRestClient*)restClient {
    if (restClient == nil) {
        restClient = [[DBRestClient alloc] initWithSession:[DBSession sharedSession]];
        restClient.delegate = self;
    }
    return restClient;
}

@end
