//
//  JDFacade.m
//  kneet2
//
//  Created by Created by Jason Lee on 10/1/15.
//  Copyright (c) 2015 ntels. All rights reserved.
//

@import ObjectiveC.runtime;

#import "JDFacade.h"

#import "JDUserDefaults.h"
#import "CypherUtil.h"
#import "JDUUID.h"

#import "CustomLoadingView.h"
#import "CustomImageView.h"

#import "RequestHandler.h"

//OpenSource
#import "FLEXManager.h"
#import "UIView+Toast.h"
#import "JDProgressHUD.h"
#import "Valet.h"
#import "VALValet.h"

#import "LoginViewController.h"
#import "MainViewController.h"
#import "DeviceModel.h"

@interface JDFacade () {
    VALValet *_valet;
    JDProgressHUD *_HUD;
    
    NSTimer *_homehubBackgroundTimer;
}

@end

@implementation JDFacade

@synthesize tmpEmailId = _tmpEmailId;

#pragma mark - Properties

- (NSString *)deviceUUID {
    if (!_deviceUUID) {
        _deviceUUID = [[JDUUID UUIDHandler] getUUID];
    }
    return _deviceUUID;
}

- (NSString *)APNSToken {
    return _APNSToken ? _APNSToken : ksEmptyString;
}

- (NSString *)tmpEmailId {
    //FIXME : 다시 생각해바,
    NSString *enTmpEmailId = [self objectForKeyFromUserDefaults:USDEF_APP_TMP_EMAIL];
    _tmpEmailId = [CypherUtil AES128Decrypt:enTmpEmailId WithKey:[CommonUtil bundleIdentifier]];
    
    return _tmpEmailId ? _tmpEmailId : ksEmptyString;
}

- (void)setTmpEmailId:(NSString *)tmpEmailId {
    
    NSString *enTmpEmailId = [CypherUtil AES128Encrypt:tmpEmailId WithKey:[CommonUtil bundleIdentifier]];
    [self storeObjectToUserDefaults:enTmpEmailId forKey:USDEF_APP_TMP_EMAIL];
}

- (void)setCurrentOperation:(NSOperation *)currentOperation {
    [CustomLoadingView loadingView].operation = currentOperation;
}

- (NSString *)deviceHostName {
    return [self hostnameOfDevice];
}

- (void)setLoginUser:(LoginModel *)loginUser {
    _loginUser = loginUser;
    
    if (!_loginUser) {
        if (_homehubBackgroundTimer) {
            [_homehubBackgroundTimer invalidate];
            _homehubBackgroundTimer = nil;
        }
    }
}

- (NSString *)hostnameOfDevice {
    char baseHostName[256];
    int success = gethostname(baseHostName, 255);
    if (success != 0) return nil;
    baseHostName[255] = '\0';
    
#if !TARGET_IPHONE_SIMULATOR
    return [NSString stringWithFormat:@"%s.local", baseHostName];
#else
    return [NSString stringWithFormat:@"%s", baseHostName];
#endif
}


#pragma mark - View Facade
- (AppDelegate *)appDelegate {
    return (AppDelegate *)[UIApplication sharedApplication].delegate;
}

#pragma mark - 화면 제어
- (UIViewController *)currentViewController {

    id appDelegate = [UIApplication sharedApplication].delegate;
    UIViewController *vc = (UINavigationController *)[[appDelegate window] rootViewController];

    if (vc.presentedViewController) {
        vc = vc.presentedViewController;

        if ([vc isKindOfClass:[UINavigationController class]]) {
            NSArray *vcArray = ((UINavigationController *)vc).viewControllers;
            vc = [vcArray objectAtIndex:vcArray.count - 1];
        }
        return vc;
    }

    if (vc.presentingViewController && (vc.modalPresentationStyle == UIModalPresentationFullScreen)) {
        vc = vc.presentingViewController;
    }

    if ([vc isKindOfClass:[UINavigationController class]]) {
        NSArray *vcArray = ((UINavigationController *)vc).viewControllers;
        vc = [vcArray objectAtIndex:vcArray.count - 1];
    }

    return vc;
}

- (id)viewControllerOnNaviationController:(Class)viewControllerClass {

    UIViewController *targetVc = nil;
    UINavigationController *navigationController = self.currentViewController.navigationController;

    if (!navigationController) {
        navigationController = (UINavigationController *)self.currentViewController.presentingViewController;
    }

    if ([navigationController isKindOfClass:[UINavigationController class]]) {        
        for (UIViewController *vc in navigationController.viewControllers) {
            if ([vc isKindOfClass:viewControllerClass]) {
                targetVc = vc;
                break;
            }
        }
    }
    return targetVc;
}

- (id)viewControllerOnPresentingViewController:(UIViewController *)pvc viewControllerClass:(Class)viewControllerClass {
    UIViewController *vc = pvc.presentingViewController;

    if (![vc isKindOfClass:viewControllerClass]) {
        vc = [self viewControllerOnPresentingViewController:vc viewControllerClass:viewControllerClass];
    }
    return vc;
}

#pragma mark - KeychainItem Wrapper 

static NSString *const ksKeychainIdentifier = @"KNEET2ACCOUNT";
static NSString *const ksKeychainArchiveData = @"_archiveData";

- (void)storeObjectToKeychain:(id)object forKey:(NSString *)aKey {
    if (!_valet) {
        _valet = [[VALValet alloc] initWithIdentifier:ksKeychainIdentifier accessibility:VALAccessibilityWhenUnlockedThisDeviceOnly];
    }
    
    NSMutableDictionary *dict = nil;
    NSData *archiveData = [_valet objectForKey:ksKeychainArchiveData];
    
    if (archiveData) {
        dict = (NSMutableDictionary *)[NSKeyedUnarchiver unarchiveObjectWithData:archiveData];
    }
    
    if (!dict) {
        dict = [[NSMutableDictionary alloc] init];
    }
    
    
    [dict setObject:object forKey:aKey];
    
    archiveData = [NSKeyedArchiver archivedDataWithRootObject:dict];
    [_valet setObject:archiveData forKey:ksKeychainArchiveData];
}

- (id)objectForKeyFromKeychain:(NSString *)aKey {
    if (!_valet) {
        _valet = [[VALValet alloc] initWithIdentifier:ksKeychainIdentifier accessibility:VALAccessibilityWhenUnlockedThisDeviceOnly];
    }
    
    NSMutableDictionary *dict = nil;
    NSData *archiveData = [_valet objectForKey:ksKeychainArchiveData];
    
    id obj = nil;
    if (archiveData) {
        dict = (NSMutableDictionary *)[NSKeyedUnarchiver unarchiveObjectWithData:archiveData];
        obj = [dict objectForKey:aKey];
    }
    
    return obj;
}

- (void)removeObjectAtKeychain:(NSString *)aKey {
    if (!_valet) {
        _valet = [[VALValet alloc] initWithIdentifier:ksKeychainIdentifier accessibility:VALAccessibilityWhenUnlockedThisDeviceOnly];
    }
    
    NSMutableDictionary *dict = nil;
    NSData *archiveData = [_valet objectForKey:ksKeychainArchiveData];
    if (archiveData) {
        NSMutableDictionary *dict = (NSMutableDictionary *)[NSKeyedUnarchiver unarchiveObjectWithData:archiveData];
        [dict removeObjectForKey:aKey];
    }
    
    archiveData = [NSKeyedArchiver archivedDataWithRootObject:dict];
    [_valet setObject:archiveData forKey:ksKeychainArchiveData];
}


#pragma mark - UserDefautls - Local Store
- (void)storeObjectToUserDefaults:(id)object forKey:(NSString *)aKey {
    [[JDUserDefaults defaults] syncronizeObject:object forKey:aKey];
}

- (id)objectForKeyFromUserDefaults:(NSString *)aKey {
    return [[JDUserDefaults defaults] objectForKey:aKey];
}


#pragma mark - Alert & Loading
- (void)loadIndicator:(BOOL)showIndicator allowUserInteraction:(BOOL)allowUserInteracton {
    
    //로딩시 터치 방지
    if(showIndicator) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [[JDFacade facade].currentViewController.view endEditing:YES];
            
            UIView *topView = [CommonUtil topView];
            [[CustomLoadingView loadingView] showInView:topView];
        });
        
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
    } else {
        
        dispatch_async(dispatch_get_main_queue(), ^{
            [[CustomLoadingView loadingView] hide];
        });
        
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    }
}

- (void)showLoadingWhileExecutingBlock:(dispatch_block_t)block completionHandler:(JDFacadeCompletionCallBackHandler)completion {
    [[CustomLoadingView loadingView] showInView:[CommonUtil topView] whileExecutingBlock:block completionHandler:completion];
}


#pragma mark - Alert UI
- (void)alert:(NSString *)message {
    [self alertTitle:@"알림" message:message];
}

- (void)alertTitle:(NSString *)title message:(NSString *)message {
    [self.currentViewController.view endEditing:YES];
    
    CustomAlertView *alert = [[CustomAlertView alloc] initWithTitle:title message:message delegate:nil OKButtonTitle:@"확인" cancelButtonTitle:nil];
    [alert show];
}

- (void)alert:(NSString *)message completionHander:(JDFacadeCompletionCallBackHandler)completion {
    [self alertTitle:@"알림" message:message completionHander:completion];
}

- (void)alertTitle:(NSString *)title message:(NSString *)message completionHander:(JDFacadeCompletionCallBackHandler)completion {
    CustomAlertView *alert = [[CustomAlertView alloc] initWithTitle:title message:message delegate:nil OKButtonTitle:@"확인" cancelButtonTitle:nil];
    
    [alert showWithCompletion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
        if (completion) {
            completion();
        }
    }];
}

- (void)confirm:(NSString *)message completion:(CustomAlertViewCallBackHandler)completion {
    [self confirmTitle:@"알림" message:message completion:completion];
}

- (void)confirmTitle:(NSString *)title message:(NSString *)message completion:(CustomAlertViewCallBackHandler)completion {
    CustomAlertView *alert = [[CustomAlertView alloc] initWithTitle:title message:message delegate:nil OKButtonTitle:@"확인" cancelButtonTitle:@"취소"];
    
    [alert showWithCompletion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
        if (completion) {
            completion(alertView, buttonIndex);
        }
    }];
}

- (void)retryAlert:(NSString *)message target:(id)target selector:(SEL)selector {
    CustomAlertView *alert = [[CustomAlertView alloc] initWithTitle:@"알림" message:message delegate:nil OKButtonTitle:@"확인" cancelButtonTitle:@"재시도"];
    [alert showWithCompletion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
        if (buttonIndex == 1) {
            if ([target respondsToSelector:selector]) {
                [target performSelector:selector withObject:nil afterDelay:0.0f];
            }
        }
    }];
}

- (void)retryAlert:(NSString *)message target:(id)target selector:(SEL)selector arguments:(id)arguments,... {
    va_list args;
    va_start(args, arguments);
    
    NSInteger i = 0;
    NSMutableArray *argsArray = [[NSMutableArray alloc] init];
    
    [argsArray addObject:arguments];
    while ((arguments = va_arg(args, id)) != nil) {//루프 - 입력된 메시지를 받아옴.
        [argsArray addObject:arguments];
        i++;
    }
    
    va_end(args);
    
    CustomAlertView *alert = [[CustomAlertView alloc] initWithTitle:@"알림" message:message delegate:nil OKButtonTitle:@"확인" cancelButtonTitle:@"재시도"];
    [alert showWithCompletion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
        if (buttonIndex == 0) {

            if (target && selector) {
                
                NSMethodSignature *sig = [target methodSignatureForSelector:selector];
                NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig];
                NSInteger index = 2;
                
                [invocation setTarget:target];                    // index 0 (hidden)
                [invocation setSelector:selector];                 //index 1 (hidden)
                
                for (id argument in argsArray) {
                    [invocation setArgument:(void *)&argument atIndex:index++];
                }
                
                [invocation invoke];
            }
        }
    }];
}

- (void)retryAlert:(NSString *)message completionHander:(JDFacadeCompletionCallBackHandler)handler {
    
    CustomAlertView *alert = [[CustomAlertView alloc] initWithTitle:@"알림" message:message delegate:nil OKButtonTitle:@"확인" cancelButtonTitle:@"재시도"];
    [alert showWithCompletion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
        if (buttonIndex == 1) {//재시도
            if (handler) {
                handler();
            }
        }
    }];
}




- (void)fireLocalNotification:(NSString *)message {
    NSLog(@"fireLocalNotification %@", message);

    NSDate *now = [NSDate date];

    UILocalNotification *localNotif = [[UILocalNotification alloc] init];
    localNotif.fireDate             = now;
    NSTimeZone* timezone            = [NSTimeZone defaultTimeZone];

    localNotif.timeZone             = timezone;
    localNotif.hasAction            = YES;
    localNotif.alertBody            = message;
    localNotif.alertAction          = @"View";

    localNotif.soundName            = UILocalNotificationDefaultSoundName;
    localNotif.applicationIconBadgeNumber = [UIApplication sharedApplication].applicationIconBadgeNumber + 1;

    [[UIApplication sharedApplication] scheduleLocalNotification:localNotif];
}

- (void)toast:(NSString *)message {
    [[CommonUtil topView] makeToast:message];
}


#pragma mark - CheckBox && Radiobutton Status

- (id)getRadioButtonStatus:(id)object {
    return objc_getAssociatedObject(object, ksCustomRadioButtonStatus);
}

- (void)setRadioButtonStatus:(id)status object:(id)object {
    objc_setAssociatedObject(object, ksCustomRadioButtonStatus, status, OBJC_ASSOCIATION_COPY_NONATOMIC); //for radio box
}

- (id)getCheckBoxStatus:(id)object {
    return objc_getAssociatedObject(object, ksCustomCheckBoxStatus);
}

- (void)setCheckBoxStatus:(id)status object:(id)object {
    objc_setAssociatedObject(object, ksCustomCheckBoxStatus, status, OBJC_ASSOCIATION_COPY_NONATOMIC); //for check box
}


#pragma mark - 화면이동 제어

- (void)dismissModalStack:(BOOL)animated completion:(JDFacadeCompletionCallBackHandler)completion {
    UIViewController *vc = self.currentViewController;
    while (vc.presentingViewController) {
        vc = vc.presentingViewController;
    }

    CATransition *transition = [CATransition animation];
    transition.duration = kfTransitionRightDur;
    transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    transition.type = kCATransitionMoveIn;
    transition.subtype = kCATransitionFromBottom;
    
    [vc.view.window.layer addAnimation:transition forKey:nil];
    [vc dismissViewControllerAnimated:NO completion:^{
        if (completion) {
            completion();
        }
    }];
}

- (void)presentViewControllerByPush:(UIViewController *)vc {

    CATransition *transition = [CATransition animation];
    transition.duration = kfTransitionRightDur;
    transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    transition.type = kCATransitionPush;
    transition.subtype = kCATransitionFromRight;
    [self.currentViewController.view.window.layer addAnimation:transition forKey:nil];

    [self.currentViewController presentViewController:vc animated:NO completion:nil];
}

- (void)presentViewControllerByPush:(UIViewController *)vc pvc:(UIViewController *)pvc {

    CATransition *transition = [CATransition animation];
    transition.duration = kfTransitionRightDur;
    transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    transition.type = kCATransitionPush;
    transition.subtype = kCATransitionFromRight;
    [pvc.view.window.layer addAnimation:transition forKey:nil];

    [pvc presentViewController:vc animated:NO completion:nil];
}

- (UIViewController *)presentedViewController:(UIViewController *)vc {
    UIViewController *presentedViewController = vc.presentedViewController;
    if (presentedViewController) {
        return [self presentedViewController:presentedViewController];
    }
    return vc;
}

- (void)dismissViewControllerByPush:(UIViewController *)vc {

    CATransition *transition = [CATransition animation];
    transition.duration = kfTransitionRightDur;
    transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    transition.type = kCATransitionPush;
    transition.subtype = kCATransitionFromBottom;

    UIViewController *presentedViewController = [self presentedViewController:vc];

    [presentedViewController.view.window.layer addAnimation:transition forKey:nil];
    [vc dismissViewControllerAnimated:NO completion:nil];
}

- (void)dismissViewControllerByPush:(UIViewController *)vc completion:(JDFacadeCompletionCallBackHandler)completion {

    CATransition *transition = [CATransition animation];
    transition.duration = kfTransitionRightDur;
    transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    transition.type = kCATransitionPush;
    transition.subtype = kCATransitionFromLeft;

    UIViewController *presentedViewController = [self presentedViewController:vc];

    [presentedViewController.view.window.layer addAnimation:transition forKey:nil];
    [vc dismissViewControllerAnimated:NO completion:^{
        if (completion) {
            completion();
        }
    }];
}

- (void)dismissAllViewControllers {
    UIViewController *vc = self.currentViewController;
    
    if (vc.presentingViewController) {
        [vc dismissViewControllerAnimated:NO completion:^{
            [self dismissAllViewControllers];
        }];
    }
}

#pragma mark - Biz Logic
- (void)checkHomeHubStatus {
    //schedul timer.
    if (!_homehubBackgroundTimer) {
        _homehubBackgroundTimer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(checkHomeHubStatus) userInfo:nil repeats:YES];
    }

    NSString *path = API_GET_DEVICE_HOMEHUB_STATUS;
    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{//RUN to background thread
        DeviceModel *homehub = [[RequestHandler handler] sendSyncGetRequestAPIPath:path parameters:nil
                                                                         modelClass:[DeviceModel class] showLoadingView:YES];
        if (homehub) {
                
            if (![[JDFacade facade].loginUser.homehubOnlineState isEqualToString:homehub.onlineState]) {
                //FIXME : real
                [JDFacade facade].loginUser.homehubOnlineState = @"ON";//homehub.onlineState;
                
                [_mainViewController updateHomeHubStatusToChildViewController];
            }
            
#ifdef DEBUG_MODE
            NSLogInfo(@"==########== homehub state = %@ ==########==", [JDFacade facade].loginUser.homehubOnlineState);
#endif
        }
        //TODO: update global - homehub state
    });
}

#pragma mark - UI Flow
- (void)gotoLoginView {
    UIViewController *vc = [CommonUtil instantiateViewControllerWithIdentifier:@"LoginViewController" storyboardName:@"Main"];
    [JDFacade facade].appDelegate.window.rootViewController = vc;
}

//- (void)gotoLoginViewWithExpiring {
//    LoginViewController *vc = [CommonUtil instantiateViewControllerWithIdentifier:@"LoginViewController" storyboardName:@"Main"];
//    [vc actionAfterLogout];
//}
//
- (void)logout {
    
    LoginViewController *lvc = (LoginViewController *)[CommonUtil instantiateViewControllerWithIdentifier:@"LoginViewController" storyboardName:@"Main"];
    [lvc requestLogout];
}

- (void)loadInvitationView {
    
    UIViewController *vc = [CommonUtil instantiateViewControllerWithIdentifier:@"InvitationListViewController" storyboardName:@"Main"];
    [self.currentViewController presentViewController:vc animated:YES completion:nil];
}

//- (void)checkDefaultHome {
//    if (!self.loginUser) {//로그인이 안된 경우, 불필요함.
//        return;
//    }
//    
//    [self updateHomegrpListForLoginUser:^{
//        //1. 다른 홈이 있는지 확인 - 정렬순서대로 기본홈을 설정 - currentHome
//        if (self.loginUser.homegrpList && self.loginUser.homegrpList.count) {
//            self.loginHomeGroup = self.loginUser.homegrpList[0];
//            [self gotoWishMenu:KNMenuIdDashboard];
//            return;
//        }
//        
//        //2. 다른 홈이 없는 경우, - 홈만들기로 이동함.
//        CustomAlertView *alert = [[CustomAlertView alloc] initWithTitle:NSLocalizedString(@"알림", @"알림") message:NSLocalizedString(@"현재 참여 중인 홈이 없습니다\n새로운 홈 만들기를 시작할까요?", @"현재 참여 중인 홈이 없습니다\n새로운 홈 만들기를 시작할까요?") delegate:nil OKButtonTitle:NSLocalizedString(@"확인", @"확인") cancelButtonTitle:NSLocalizedString(@"취소", @"취소")];
//        [alert showWithCompletion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
//            if (buttonIndex == 0) {//OK
//                [self gotoStartHome:NO];
//            } else {
//                [self logout];
//            }
//        }];
//    }];
//}

- (void)gotoStartHome:(BOOL)canGoBack {
//    StartHomeViewController *vc = [CommonUtil instantiateViewControllerWithIdentifier:@"StartHomeViewController" storyboardName:@"SignUp"];
//    vc.canGoBack = canGoBack;
//    [[JDFacade facade] presentViewControllerByPush:vc pvc:self.currentViewController];
}


- (void)gotoWishMenu:(KNMenuId)menuId {
    [self gotoWishMenu:menuId completion:nil];
}


- (void)gotoWishMenu:(KNMenuId)menuId completion:(JDFacadeCompletionCallBackHandler)completion {
    self.wishMenuId = menuId;
    
    switch (self.wishMenuId) {
        case KNMenuIdThings: {
            [_mainViewController loadThingsViewController];
        }
            break;
        case KNMenuIdRules: {
            [_mainViewController loadRulesViewController];
        }
            break;
        case KNMenuIdHomeMember: {
            [_mainViewController loadMembersViewController];
        }
            break;
            
        default:
            break;
    }
}


- (void)gotoHomeHubRegistration {
    UIViewController *vc = [CommonUtil instantiateViewControllerWithIdentifier:@"HomeHubStartViewController" storyboardName:@"HomeHub"];
    
    vc.providesPresentationContextTransitionStyle = YES;
    vc.definesPresentationContext = YES;
    
    [vc setModalPresentationStyle:UIModalPresentationOverCurrentContext];
    
    [self.currentViewController presentViewController:vc animated:NO completion:nil];
}

//- (void)updateHomegrpListForLoginUser:(JDFacadeCompletionCallBackHandler)completion {
//    
//    NSDictionary *parameter = @{@"device_sn": [JDFacade facade].deviceUUID};
//    
//    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{//RUN to background thread
//        HomeGroupListModel *homegrpList = [[RequestHandler handler] sendSyncGetRequestAPIPath:API_GET_HOMEGROUP parameters:parameter
//                                                                                   modelClass:[HomeGroupListModel class] showLoadingView:YES];
//        
//        
//        //        NSLog(@"%s\n %@", __PRETTY_FUNCTION__, homegrpList);
//        //홈그룹을 설정함.
//        self.loginUser.homegrpList = homegrpList && homegrpList.homegrpList ? homegrpList.homegrpList : nil;
//        
//        //로그인 홈을 지정함.
//        for (HomeGroupModel *homegrp in self.loginUser.homegrpList) {
//            if ([self.loginUser.homegrpId isEqualToString:homegrp.homegrpId]) {
//                self.loginHomeGroup = homegrp;
//                break;
//            }
//        }
//        
////        [[LocationHandler handler] resetAllMonitoredRegions];   //현재 앱이 구동 중이면, 위치 센서를 다시 등록해야함.
////        [[LocationHandler handler] registerGeofencingForHomeGroupIndex:0];  //모든 홈 그룹을 다시 모니터링 등록 - 루프
//        
//        if (completion) {
//            completion();
//        }
//    });
//}




- (void)updateLoginInfo:(JDFacadeCompletionCallBackHandler)completion {
    NSLog(@"%s\n %@", __PRETTY_FUNCTION__, [JDFacade facade].deviceUUID);
    
    NSDictionary *parameter = @{@"device_sn": [JDFacade facade].deviceUUID,
                                @"device_token": [JDFacade facade].APNSToken ? [JDFacade facade].APNSToken : ksEmptyString,
                                @"os_type": MOBILE_DEVICE_TYPE};
    
    NSString *path = [NSString stringWithFormat:API_GET_SIGN_IN_AUTO];
    
//    dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{//RUN to background thread
//        LoginModel *loginInfo = [[RequestHandler handler] sendSyncGetRequestAPIPath:path parameters:parameter
//                                                                         modelClass:[LoginModel class] showLoadingView:YES];
//        if (loginInfo) {
//            [JDFacade facade].loginUser = loginInfo;
//        }
//        
//        if (completion) {
//            completion();
//        }
//    });
}



- (void)alertLocationServiceDisabled {
    NSString *message = MSG_LOCATION_DISABLE;
    
    CustomAlertView *alert = [[CustomAlertView alloc] initWithTitle:NSLocalizedString(@"알림", @"알림") delegate:nil OKButtonTitle:NSLocalizedString(@"설정", @"설정") cancelButtonTitle:NSLocalizedString(@"취소", @"취소") message:message, nil];
    [alert showWithCompletion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
        if (buttonIndex == 0) {//OK
            NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
            [[UIApplication sharedApplication]openURL:settingsURL];
        }
    }];
}


- (void)alertCameraPermissionDisabled {
    NSString *message = MSG_CAMERA_DISABLE;
    
    CustomAlertView *alert = [[CustomAlertView alloc] initWithTitle:NSLocalizedString(@"알림", @"알림") delegate:nil OKButtonTitle:NSLocalizedString(@"설정", @"설정") cancelButtonTitle:NSLocalizedString(@"취소", @"취소") message:message, nil];
    [alert showWithCompletion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
        if (buttonIndex == 0) {//OK
            NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
            [[UIApplication sharedApplication]openURL:settingsURL];
        }
    }];
}


#pragma mark - Debug
- (void)showFlex {
    [[FLEXManager sharedManager] showExplorer];
}

- (BOOL)redirectNSLog {

    // Create log file
    NSDate *date = [NSDate date];
    NSDateFormatter *df = [CommonUtil dateFormatter];
    [df setDateFormat:@"yyyyMMddHHmmss"];
    NSString *sdate = [df stringFromDate:date];


    NSString *logPath = [NSString stringWithFormat:@"%@/log_%@.txt", NSTemporaryDirectory(), sdate];
    [@"" writeToFile:logPath atomically:YES encoding:NSUTF8StringEncoding error:nil];

    id fileHandle = [NSFileHandle fileHandleForWritingAtPath:logPath];
    if (!fileHandle) {
        NSLog(@"Opening log failed");
        return NO;
    }
    // Redirect stderr

    int err = dup2([fileHandle fileDescriptor], STDERR_FILENO);

    if (!err) {
        NSLog(@"Couldn't redirect stderr");
        return NO;
    }
    return	YES;
}

#pragma mark - Singleton

+ (JDFacade *)facade {

    static JDFacade *sharedJSFacade = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedJSFacade = [[self alloc] init];
    });
    return sharedJSFacade;
}

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


@end
