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

#import "UIViewController+Permissions.h"
#import "Session-Swift.h"
#import <AVFoundation/AVFoundation.h>
#import <Photos/Photos.h>
#import <SignalCoreKit/Threading.h>
#import <SignalUtilitiesKit/UIUtil.h>

NS_ASSUME_NONNULL_BEGIN

@implementation UIViewController (Permissions)

- (void)ows_askForCameraPermissions:(void (^)(BOOL granted))callbackParam
{
    OWSLogVerbose(@"[%@] ows_askForCameraPermissions", NSStringFromClass(self.class));

    // Ensure callback is invoked on main thread.
    void (^callback)(BOOL) = ^(BOOL granted) {
        DispatchMainThreadSafe(^{
            callbackParam(granted);
        });
    };

    if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
        OWSLogError(@"Skipping camera permissions request when app is in background.");
        callback(NO);
        return;
    }

    if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
        OWSLogError(@"Camera ImagePicker source not available");
        callback(NO);
        return;
    }

    AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    if (status == AVAuthorizationStatusDenied) {
        UIAlertController *alert = [UIAlertController
            alertControllerWithTitle:NSLocalizedString(@"Session needs camera access to scan QR codes.", @"")
                             message:NSLocalizedString(@"You can enable camera access in your device settings.", @"")
                      preferredStyle:UIAlertControllerStyleAlert];

        UIAlertAction *openSettingsAction =
            [UIAlertAction actionWithTitle:CommonStrings.openSettingsButton
                                     style:UIAlertActionStyleDefault
                                   handler:^(UIAlertAction *_Nonnull action) {
                                       [[UIApplication sharedApplication] openSystemSettings];
                                       callback(NO);
                                   }];
        [alert addAction:openSettingsAction];

        UIAlertAction *dismissAction = [UIAlertAction actionWithTitle:CommonStrings.dismissButton
                                                                style:UIAlertActionStyleCancel
                                                              handler:^(UIAlertAction *action) {
                                                                  callback(NO);
                                                              }];
        [alert addAction:dismissAction];

        [self presentAlert:alert];
    } else if (status == AVAuthorizationStatusAuthorized) {
        callback(YES);
    } else if (status == AVAuthorizationStatusNotDetermined) {
        [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo
                                 completionHandler:callback];
    } else {
        OWSLogError(@"Unknown AVAuthorizationStatus: %ld", (long)status);
        callback(NO);
    }
}

- (void)ows_askForMediaLibraryPermissions:(void (^)(BOOL granted))callbackParam
{
    OWSLogVerbose(@"[%@] ows_askForMediaLibraryPermissions", NSStringFromClass(self.class));

    // Ensure callback is invoked on main thread.
    void (^completionCallback)(BOOL) = ^(BOOL granted) {
        DispatchMainThreadSafe(^{
            callbackParam(granted);
        });
    };

    void (^presentSettingsDialog)(void) = ^(void) {
        DispatchMainThreadSafe(^{
            UIAlertController *alert = [UIAlertController
                alertControllerWithTitle:NSLocalizedString(@"MISSING_MEDIA_LIBRARY_PERMISSION_TITLE",
                                             @"Alert title when user has previously denied media library access")
                                 message:NSLocalizedString(@"MISSING_MEDIA_LIBRARY_PERMISSION_MESSAGE",
                                             @"Alert body when user has previously denied media library access")
                          preferredStyle:UIAlertControllerStyleAlert];

            UIAlertAction *openSettingsAction =
                [UIAlertAction actionWithTitle:CommonStrings.openSettingsButton
                                         style:UIAlertActionStyleDefault
                                       handler:^(UIAlertAction *_Nonnull action) {
                                           [[UIApplication sharedApplication] openSystemSettings];
                                           completionCallback(NO);
                                       }];
            [alert addAction:openSettingsAction];

            UIAlertAction *dismissAction = [UIAlertAction actionWithTitle:CommonStrings.dismissButton
                                                                    style:UIAlertActionStyleCancel
                                                                  handler:^(UIAlertAction *action) {
                                                                      completionCallback(NO);
                                                                  }];
            [alert addAction:dismissAction];

            [self presentAlert:alert];
        });
    };

    if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
        OWSLogError(@"Skipping media library permissions request when app is in background.");
        completionCallback(NO);
        return;
    }

    if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
        OWSLogError(@"PhotoLibrary ImagePicker source not available");
        completionCallback(NO);
    }

    PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];

    switch (status) {
        case PHAuthorizationStatusAuthorized: {
            completionCallback(YES);
            return;
        }
        case PHAuthorizationStatusDenied: {
            presentSettingsDialog();
            return;
        }
        case PHAuthorizationStatusNotDetermined: {
            [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus newStatus) {
                if (newStatus == PHAuthorizationStatusAuthorized) {
                    completionCallback(YES);
                } else {
                    presentSettingsDialog();
                }
            }];
            return;
        }
        case PHAuthorizationStatusRestricted: {
            // when does this happen?
            OWSFailDebug(@"PHAuthorizationStatusRestricted");
            return;
        }
    }
}

- (void)ows_askForMicrophonePermissions:(void (^)(BOOL granted))callbackParam
{
    OWSLogVerbose(@"[%@] ows_askForMicrophonePermissions", NSStringFromClass(self.class));

    // Ensure callback is invoked on main thread.
    void (^callback)(BOOL) = ^(BOOL granted) {
        DispatchMainThreadSafe(^{
            callbackParam(granted);
        });
    };

    if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
        OWSLogError(@"Skipping microphone permissions request when app is in background.");
        callback(NO);
        return;
    }

    [[AVAudioSession sharedInstance] requestRecordPermission:callback];
}

@end

NS_ASSUME_NONNULL_END