//
//  Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//

#import "SAEScreenLockViewController.h"
#import "UIColor+OWS.h"
#import <SignalUtilitiesKit/SignalUtilitiesKit-Swift.h>
#import <SessionUtilitiesKit/AppContext.h>

NS_ASSUME_NONNULL_BEGIN

@interface SAEScreenLockViewController () <ScreenLockViewDelegate>

@property (nonatomic, readonly, weak) id<ShareViewDelegate> shareViewDelegate;

@property (nonatomic) BOOL hasShownAuthUIOnce;

@property (nonatomic) BOOL isShowingAuthUI;

@end

#pragma mark -

@implementation SAEScreenLockViewController

- (instancetype)initWithShareViewDelegate:(id<ShareViewDelegate>)shareViewDelegate
{
    self = [super init];
    if (!self) {
        return self;
    }

    _shareViewDelegate = shareViewDelegate;

    self.delegate = self;

    return self;
}

- (void)loadView
{
    [super loadView];

    UIView.appearance.tintColor = LKColors.text;
    
    // Gradient background
    self.view.backgroundColor = UIColor.clearColor;
    CAGradientLayer *layer = [CAGradientLayer new];
    layer.frame = UIScreen.mainScreen.bounds;
    UIColor *gradientStartColor = LKAppModeUtilities.isLightMode ? [UIColor colorWithRGBHex:0xFCFCFC] : [UIColor colorWithRGBHex:0x171717];
    UIColor *gradientEndColor = LKAppModeUtilities.isLightMode ? [UIColor colorWithRGBHex:0xFFFFFF] : [UIColor colorWithRGBHex:0x121212];
    layer.colors = @[ (id)gradientStartColor.CGColor, (id)gradientEndColor.CGColor ];
    [self.view.layer insertSublayer:layer atIndex:0];
    
    // Navigation bar background color
    UINavigationBar *navigationBar = self.navigationController.navigationBar;
    [navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
    navigationBar.shadowImage = [UIImage new];
    [navigationBar setTranslucent:NO];
    navigationBar.barTintColor = LKColors.navigationBarBackground;

    // Title
    UILabel *titleLabel = [UILabel new];
    titleLabel.text = NSLocalizedString(@"vc_share_title", @"");
    titleLabel.textColor = LKColors.text;
    titleLabel.font = [UIFont boldSystemFontOfSize:LKValues.veryLargeFontSize];
    self.navigationItem.titleView = titleLabel;

    // Close button
    UIBarButtonItem *closeButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"X"] style:UIBarButtonItemStylePlain target:self action:@selector(dismissPressed:)];
    closeButton.tintColor = LKColors.text;
    self.navigationItem.leftBarButtonItem = closeButton;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    [self ensureUI];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    [self ensureUI];

    // Auto-show the auth UI f
    if (!self.hasShownAuthUIOnce) {
        self.hasShownAuthUIOnce = YES;

        [self tryToPresentAuthUIToUnlockScreenLock];
    }
}

- (void)dealloc
{
    // Surface memory leaks by logging the deallocation of view controllers.
    OWSLogVerbose(@"Dealloc: %@", self.class);
}

- (void)tryToPresentAuthUIToUnlockScreenLock
{
    OWSAssertIsOnMainThread();

    if (self.isShowingAuthUI) {
        // We're already showing the auth UI; abort.
        return;
    }
    OWSLogInfo(@"try to unlock screen lock");

    self.isShowingAuthUI = YES;

    [OWSScreenLock.sharedManager tryToUnlockScreenLockWithSuccess:^{
        OWSAssertIsOnMainThread();

        OWSLogInfo(@"unlock screen lock succeeded.");

        self.isShowingAuthUI = NO;

        [self.shareViewDelegate shareViewWasUnlocked];
    }
        failure:^(NSError *error) {
            OWSAssertIsOnMainThread();

            OWSLogInfo(@"unlock screen lock failed.");

            self.isShowingAuthUI = NO;

            [self ensureUI];

            [self showScreenLockFailureAlertWithMessage:error.localizedDescription];
        }
        unexpectedFailure:^(NSError *error) {
            OWSAssertIsOnMainThread();

            OWSLogInfo(@"unlock screen lock unexpectedly failed.");

            self.isShowingAuthUI = NO;

            // Local Authentication isn't working properly.
            // This isn't covered by the docs or the forums but in practice
            // it appears to be effective to retry again after waiting a bit.
            dispatch_async(dispatch_get_main_queue(), ^{
                [self ensureUI];
            });
        }
        cancel:^{
            OWSAssertIsOnMainThread();

            OWSLogInfo(@"unlock screen lock cancelled.");

            self.isShowingAuthUI = NO;

            [self ensureUI];
        }];

    [self ensureUI];
}

- (void)ensureUI
{
    [self updateUIWithState:ScreenLockUIStateScreenLock isLogoAtTop:NO animated:NO];
}

- (void)showScreenLockFailureAlertWithMessage:(NSString *)message
{
    OWSAssertIsOnMainThread();

    [OWSAlerts showAlertWithTitle:NSLocalizedString(@"SCREEN_LOCK_UNLOCK_FAILED",
                                      @"Title for alert indicating that screen lock could not be unlocked.")
                          message:message
                      buttonTitle:nil
                     buttonAction:^(UIAlertAction *action) {
                         // After the alert, update the UI.
                         [self ensureUI];
                     }
               fromViewController:self];
}

- (void)dismissPressed:(id)sender
{
    OWSLogDebug(@"tapped dismiss share button");

    [self cancelShareExperience];
}

- (void)cancelShareExperience
{
    [self.shareViewDelegate shareViewWasCancelled];
}

#pragma mark - ScreenLockViewDelegate

- (void)unlockButtonWasTapped
{
    OWSAssertIsOnMainThread();

    OWSLogInfo(@"unlockButtonWasTapped");

    [self tryToPresentAuthUIToUnlockScreenLock];
}

@end

NS_ASSUME_NONNULL_END