import Photos
import AVFoundation
import LocalAuthentication

public protocol PermissionHandling {
    var isCameraAllowed: Bool { get }
    var isPhotosAllowed: Bool { get }
    var isMicrophoneAllowed: Bool { get }
    var isBiometricsAvailable: Bool { get }

    func requestPhotos(_: @escaping (Bool) -> Void)
    func requestCamera(_: @escaping (Bool) -> Void)
    func requestMicrophone(_: @escaping (Bool) -> Void)
    func requestBiometrics(_: @escaping (Result<Bool, Error>) -> Void)
}

public struct PermissionHandler: PermissionHandling {
    public init() {}

    public var isMicrophoneAllowed: Bool {
        AVAudioSession.sharedInstance().recordPermission == .granted
    }

    public var isCameraAllowed: Bool {
        AVCaptureDevice.authorizationStatus(for: .video) ==  .authorized
    }

    public var isPhotosAllowed: Bool {
        PHPhotoLibrary.authorizationStatus() == .authorized
    }

    public var isBiometricsAvailable: Bool {
        var error: NSError?
        let context = LAContext()

        if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) == true {
            return true
        } else {
            let tooManyAttempts = LAError.Code.biometryLockout.rawValue
            guard let error = error, error.code == tooManyAttempts else { return true }
            return false
        }
    }

    public func requestBiometrics(_ completion: @escaping (Result<Bool, Error>) -> Void) {
        let reason = "Authentication is required to use xx messenger"
        LAContext().evaluatePolicy(.deviceOwnerAuthentication, localizedReason: reason, reply: { success, error in
            guard let error = error else {
                completion(.success(success))
                return
            }

            completion(.failure(error))
        })
    }

    public func requestCamera(_ completion: @escaping (Bool) -> Void) {
        AVCaptureDevice.requestAccess(for: .video, completionHandler: completion)
    }

    public func requestMicrophone(_ completion: @escaping (Bool) -> Void) {
        AVAudioSession.sharedInstance().requestRecordPermission(completion)
    }

    public func requestPhotos(_ completion: @escaping (Bool) -> Void) {
        PHPhotoLibrary.requestAuthorization { completion($0 == .authorized) }
    }
}