<commit_before>//
//  LocationManager.swift
//  Pods
//
//  Created by <NAME> on 20/05/15.
//  Copyright © 2015 The Funtasty. All rights reserved.
//
//

import CoreLocation
import PromiseKit

public enum LocationManagerError: Error {
    case locationServiceDisabled
    case cannotFetchLocation
}

public enum LocationManagerAuthorizationError: Error {
    case keyInPlistMissing
}

open class LocationManager: NSObject, CLLocationManagerDelegate {

    typealias AuthorizationFulfillment = (CLAuthorizationStatus) -> Void

    @objc public static let locationDidChangeAuthorizationStatusNotification = "locationDidChangeAuthorizationStatusNotification"
    @objc public static let sharedManager = LocationManager()

    @objc var currentLocation: CLLocation?
    @objc internal var lastKnownLocation: CLLocation?
    
    fileprivate var locationRequests = [LocationRequest]()
    fileprivate var locationObservers: Set<LocationObserverItem> = []
    fileprivate var askForLocationServicesFulfillments = [AuthorizationFulfillment]()
    fileprivate let locationManager = CLLocationManager()

    @objc public static var locationObserversCount: Int {
        return self.sharedManager.locationObserversCount
    }
    @objc open var locationObserversCount: Int {
        return self.locationObservers.count
    }

    public override init() {

        super.init()

        self.locationManager.delegate = self
        self.locationManager.distanceFilter = 0
        self.locationManager.desiredAccuracy = 0
    }
    
    @objc open class func isLocationStatusDetermined() -> Bool {
        return self.sharedManager.isLocationStatusDetermined()
    }
    
    @objc open func isLocationStatusDetermined() -> Bool {
        return CLLocationManager.authorizationStatus() != CLAuthorizationStatus.notDetermined
    }
    
    @objc open class func isLocationAvailable() -> Bool {
        return sharedManager.isLocationAvailable()
    }
    
    @objc open func isLocationAvailable() -> Bool {
        return CLLocationManager.locationServicesEnabled() && (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedAlways || CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedWhenInUse)
    }
    
    /**
     * Checks for authorization status of location services
     * returns promise for authorization status on success, LocationManagerAuthorizationError on fail
     */
    
    open class func askForLocationServicesIfNeeded() -> Promise<CLAuthorizationStatus> {
        return self.sharedManager.askForLocationServicesIfNeeded()
    }
    
    open func askForLocationServicesIfNeeded() -> Promise<CLAuthorizationStatus> {

        let promise = Promise<CLAuthorizationStatus> { seal in
            if isLocationStatusDetermined() {
                return seal.fulfill(CLLocationManager.authorizationStatus())
            }
            
            askWith(fulfillment: { (status: CLAuthorizationStatus) -> Void in
                seal.fulfill(status)
            }, rejection: seal.reject)
        }
        return promise
        
    }
    
    fileprivate func askWith(fulfillment: @escaping AuthorizationFulfillment, rejection: (Error) -> Void) -> Void {

        var rejected = false

        if askForLocationServicesFulfillments.count == 0 {

            if Bundle.main.object(forInfoDictionaryKey: "NSLocationAlwaysUsageDescription") != nil {

                if locationManager.responds(to: #selector(CLLocationManager.requestAlwaysAuthorization)) {
                    locationManager.requestAlwaysAuthorization()
                }

            } else if Bundle.main.object(forInfoDictionaryKey: "NSLocationWhenInUseUsageDescription") != nil {

                if locationManager.responds(to: #selector(CLLocationManager.requestWhenInUseAuthorization)) {
                    locationManager.requestWhenInUseAuthorization();
                }

            } else {

                rejection(LocationManagerAuthorizationError.keyInPlistMissing)
                rejected = true
            }
        }

        if !rejected {
            askForLocationServicesFulfillments.append(fulfillment)
        }
    }
    
    @objc func startUpdatingLocationIfNeeded() {

        if !locationRequests.isEmpty || !locationObservers.isEmpty {

            _ = askForLocationServicesIfNeeded()
            locationManager.startUpdatingLocation()
        }

        updateLocationManagerSettings()
    }
    
    @objc func stopUpdatingLocationIfPossible() {

        if locationRequests.isEmpty && locationObservers.isEmpty {
            locationManager.stopUpdatingLocation()
        }

        updateLocationManagerSettings()
    }
    
    @objc func updateLocationManagerSettings() {

        let requestsDesiredAccuracy = locationRequests.map { (request) -> CLLocationAccuracy in
            return request.desiredAccuracy ?? 0
        }.min() ?? 0
        
        let observersDesiredAccuracy = locationObservers.map { (observer) -> CLLocationAccuracy in
            return observer.desiredAccuracy ?? 0
        }.min() ?? 0
        
        let desiredAccuracy = min(requestsDesiredAccuracy,observersDesiredAccuracy)

        if locationManager.desiredAccuracy != desiredAccuracy {
           locationManager.desiredAccuracy = desiredAccuracy
        }
        
        if locationRequests.count == 0 {

            let observersDistanceFilter = locationObservers.map { (observer) -> CLLocationAccuracy in
                return observer.distanceFilter ?? 0
            }.min() ?? 0
            <commit_msg>refactored askWith() to avoid usage of var<commit_after>//
//  LocationManager.swift
//  Pods
//
//  Created by <NAME> on 20/05/15.
//  Copyright © 2015 The Funtasty. All rights reserved.
//
//

import CoreLocation
import PromiseKit

public enum LocationManagerError: Error {
    case locationServiceDisabled
    case cannotFetchLocation
}

public enum LocationManagerAuthorizationError: Error {
    case keyInPlistMissing
}

open class LocationManager: NSObject, CLLocationManagerDelegate {

    typealias AuthorizationFulfillment = (CLAuthorizationStatus) -> Void

    @objc public static let locationDidChangeAuthorizationStatusNotification = "locationDidChangeAuthorizationStatusNotification"
    @objc public static let sharedManager = LocationManager()

    @objc var currentLocation: CLLocation?
    @objc internal var lastKnownLocation: CLLocation?
    
    fileprivate var locationRequests = [LocationRequest]()
    fileprivate var locationObservers: Set<LocationObserverItem> = []
    fileprivate var askForLocationServicesFulfillments = [AuthorizationFulfillment]()
    fileprivate let locationManager = CLLocationManager()

    @objc public static var locationObserversCount: Int {
        return self.sharedManager.locationObserversCount
    }
    @objc open var locationObserversCount: Int {
        return self.locationObservers.count
    }

    public override init() {

        super.init()

        self.locationManager.delegate = self
        self.locationManager.distanceFilter = 0
        self.locationManager.desiredAccuracy = 0
    }
    
    @objc open class func isLocationStatusDetermined() -> Bool {
        return self.sharedManager.isLocationStatusDetermined()
    }
    
    @objc open func isLocationStatusDetermined() -> Bool {
        return CLLocationManager.authorizationStatus() != CLAuthorizationStatus.notDetermined
    }
    
    @objc open class func isLocationAvailable() -> Bool {
        return sharedManager.isLocationAvailable()
    }
    
    @objc open func isLocationAvailable() -> Bool {
        return CLLocationManager.locationServicesEnabled() && (CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedAlways || CLLocationManager.authorizationStatus() == CLAuthorizationStatus.authorizedWhenInUse)
    }
    
    /**
     * Checks for authorization status of location services
     * returns promise for authorization status on success, LocationManagerAuthorizationError on fail
     */
    
    open class func askForLocationServicesIfNeeded() -> Promise<CLAuthorizationStatus> {
        return self.sharedManager.askForLocationServicesIfNeeded()
    }
    
    open func askForLocationServicesIfNeeded() -> Promise<CLAuthorizationStatus> {

        let promise = Promise<CLAuthorizationStatus> { seal in
            if isLocationStatusDetermined() {
                return seal.fulfill(CLLocationManager.authorizationStatus())
            }
            
            askWith(fulfillment: { (status: CLAuthorizationStatus) -> Void in
                seal.fulfill(status)
            }, rejection: seal.reject)
        }
        return promise
        
    }
    
    fileprivate func askWith(fulfillment: @escaping AuthorizationFulfillment, rejection: (Error) -> Void) -> Void {

        if !setupRequestPermissionsStrategy(rejection: rejection) {
            askForLocationServicesFulfillments.append(fulfillment)
        }
    }
    
    private func setupRequestPermissionsStrategy(rejection: (Error) -> Void) -> Bool {
        
        if askForLocationServicesFulfillments.isEmpty {
            
            if Bundle.main.object(forInfoDictionaryKey: "NSLocationAlwaysUsageDescription") != nil {
                
                if locationManager.responds(to: #selector(CLLocationManager.requestAlwaysAuthorization)) {
                    locationManager.requestAlwaysAuthorization()
                }
                
            } else if Bundle.main.object(forInfoDictionaryKey: "NSLocationWhenInUseUsageDescription") != nil {
                
                if locationManager.responds(to: #selector(CLLocationManager.requestWhenInUseAuthorization)) {
                    locationManager.requestWhenInUseAuthorization();
                }
                
            } else {
                
                rejection(LocationManagerAuthorizationError.keyInPlistMissing)
                return true
            }
        }
        return false
    }
    
    @objc func startUpdatingLocationIfNeeded() {

        if !locationRequests.isEmpty || !locationObservers.isEmpty {

            _ = askForLocationServicesIfNeeded()
            locationManager.startUpdatingLocation()
        }

        updateLocationManagerSettings()
    }
    
    @objc func stopUpdatingLocationIfPossible() {

        if locationRequests.isEmpty && locationObservers.isEmpty {
            locationManager.stopUpdatingLocation()
        }

        updateLocationManagerSettings()
    }
    
    @objc func updateLocationManagerSettings() {

        let requestsDesiredAccuracy = locationRequests.map { (request) -> CLLocationAccuracy in
            return request.desiredAccuracy ?? 0
        }.min() ?? 0
        
        let observersDesiredAccuracy = locationObservers.map { (observer) -> CLLocationAccuracy in
            return observer.desiredAccuracy ?? 0
        }.min() ?? 0
        
        let desiredAccuracy = min(requestsDesiredAccuracy,observersDesiredAccuracy)

        if locationManager.desiredAccuracy != desiredAccuracy {
           locationManager.desiredAccuracy = desiredAccuracy
        }
        
        if locationRequests.isEmpty {

            let observersDistanceFilter = locationObservers.map { (observer) -> CLLocationAccuracy in
                return observer.distanceFilter ?? 0
            }.min() ?? 0
            
{'fraction_non_alphanumeric': 0.072752833670152, 'fraction_numerical': 0.00333889816360601, 'mean_word_length': 2.6894651539708265, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1862021', 'n_tokens_mistral': 2891, 'n_tokens_neox': 2798, 'n_words': 590}