//
//  LocalAuthenticationService.swift
//  wallet
//
//  Created by Pietro Basso on 20/02/2019.
//  Copyright (c) 2019 Pietro Basso. All rights reserved.
//
//  This file was generated by the Lisca Xcode Templates so
//  you can apply lisca architecture to your iOS projects
//

import LocalAuthentication
import RxSwift
import RxCocoa

protocol LocalAuthenticationServiceProvider {
    var localAuthenticationService: LocalAuthenticationService { get }
}

protocol LocalAuthenticationService {
    var state: Observable<AuthenticationState> { get }
    func authenticate(reply: @escaping (Result<Bool, Error>) -> Void)
}

class LocalAuthenticationServiceImplementation: LocalAuthenticationService {
    let state: Observable<AuthenticationState>
    private let _state = PublishSubject<AuthenticationState>()
    private let reason = "Log in to Wallet"
    private let disposeBag = DisposeBag()
    
    init() {
        state = _state
            .asObservable()
            .distinctUntilChanged()
            .share(replay: 1, scope: .forever)
        state
            .subscribe()
            .disposed(by: disposeBag)
    }
    
    func authenticate(reply: @escaping (Result<Bool, Error>) -> Void) {
        var error: NSError?
        let context = LAContext()
        let completion: (Result<Bool, Error>) -> Void = { (result) in
            DispatchQueue.main.async {
                reply(result)
            }
        }
        guard context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else {
            if let error = error {
                completion(Result(error: error))
            }
            return
        }
        context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { (success, error) in
            if let error = error {
                completion(Result(error: error))
                return
            }
            self._state.onNext(AuthenticationState(success: success))
            completion(Result(value: success))
        }
    }
}
