//
//  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 "KeychainItemWrapper.h"
#import "JDUUID.h"

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

#import "RequestHandler.h"

//OpenSource
#import "FLEXManager.h"
#import "UIView+Toast.h"

@interface JDFacade () {
    KeychainItemWrapper *_keychainItemWrapper;
}

@end

@implementation JDFacade

#pragma mark - Properties

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

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


#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 - 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 {

    UIWindow *mainWindow = [self appDelegate].window;

    //로딩시 터치 방지
    if(showIndicator) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [[JDFacade facade].currentViewController.view endEditing:YES];
            UIView *topView = [[mainWindow subviews] lastObject];
            [CustomLoadingView showWithView:topView];


            mainWindow.userInteractionEnabled = allowUserInteracton;
        });

        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
    } else {

        dispatch_async(dispatch_get_main_queue(), ^{
            [CustomLoadingView hide];

            mainWindow.userInteractionEnabled = allowUserInteracton;
        });

        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    }
}


- (void)alert:(NSString *)message {

    [self.currentViewController.view endEditing:YES];

    CustomAlertView *alert = [[CustomAlertView alloc] initWithTitle:@"알림" message:message delegate:nil OKButtonTitle:@"확인" cancelButtonTitle:nil];
    [alert show];
}


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

- (void)alert:(NSString *)message completionHander:(completionCallBackHandler)handler {
    CustomAlertView *alert = [[CustomAlertView alloc] initWithTitle:@"알림" message:message delegate:nil OKButtonTitle:@"확인" cancelButtonTitle:nil];

    [alert showWithCompletion:^(CustomAlertView *alertView, NSInteger buttonIndex) {
        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 - 화면이동 제어

- (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
}

- (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 = kCATransitionFromLeft;

    UIViewController *presentedViewController = [self presentedViewController:vc];

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

- (void)dismissViewControllerByPush:(UIViewController *)vc completion:(completionCallBackHandler)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 - 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 *pvc = [JDFacade facade].currentViewController.presentedViewController;
//    if (!pvc) {
//        pvc = [JDFacade facade].currentViewController;
//    }
//    
//    UIViewController *vc = [CommonUtil instantiateViewControllerWithIdentifier:@"InvitationListViewController" storyboardName:@"Main"];
//    [[JDFacade facade] presentViewControllerByPush:vc pvc:pvc];
//}
//
//- (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:(completionCallBackHandler)completion {
    self.wishMenuId = menuId;
    
    UIViewController *vc = self.appDelegate.window.rootViewController;
    if (vc.presentedViewController || (vc.presentingViewController && (vc.modalPresentationStyle == UIModalPresentationFullScreen))){
        [vc dismissViewControllerAnimated:YES completion:nil];
    }
    
//    MenuViewController *mvc = [JDFacade facade].menuViewController;
//    [mvc gotoWishMenu:self.wishMenuId completion:completion];
}

- (void)updateHomegrpListForLoginUser:(completionCallBackHandler)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:(completionCallBackHandler)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
