//
//  GMFGLocationManager.swift
//  MVM5G
//
//  Created by Muthulingam, Muthuraj on 03/06/20.
//  Copyright © 2020 Kyle. All rights reserved.
//

import Foundation
import CoreLocation

protocol GMFGLocationManagerDelegate: AnyObject {
     func locationManager(_ manager: GMFGLocationManager, didUpdateLocations locations: [CLLocation])
     func locationManager(_ manager: GMFGLocationManager, didHeadUpdate newHeading: CLHeading)
     func locationManager(_ manager: GMFGLocationManager, didUpdateLocationPermissions isAuthorized: Bool)
}

final class GMFGLocationManager: NSObject {
    
    // MARK: - Public Properties
    weak var delegate: GMFGLocationManagerDelegate?
    static let shared = GMFGLocationManager()
    var locationServicesEnabled: Bool {
        if CLLocationManager.locationServicesEnabled() {
            switch CLLocationManager.authorizationStatus() {
                case .notDetermined, .restricted, .denied:
                    return false
                case .authorizedAlways, .authorizedWhenInUse:
                    return true
                @unknown default:
                    return false
            }
        } else {
            return false
        }
    }
    
    /// Fetches Current Location if available
    private(set) var currentLocation: CLLocation?
    
    // MARK: - Private Properties
    private lazy var locationManager = CLLocationManager()
    
    /// to avoid called to create instance
    private override init() {
        super.init()
    }
    
    // MARK: - Public Helpers
    func prepareLocationManager() {
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.headingFilter = kCLHeadingFilterNone
        locationManager.requestWhenInUseAuthorization()
        locationManager.startUpdatingLocation()
        locationManager.startUpdatingHeading()
    }
    
    func startLocationMonitoring() {
        locationManager.startUpdatingHeading()
        locationManager.startUpdatingLocation()
    }
    
    func stopLocationMonitoring() {
        locationManager.stopUpdatingHeading()
        locationManager.stopUpdatingLocation()
    }
}

extension GMFGLocationManager: CLLocationManagerDelegate {
    
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        switch status {
            case .authorizedAlways, .authorizedWhenInUse:
                locationManager.startUpdatingLocation()
                locationManager.startUpdatingHeading()
            case .denied, .notDetermined, .restricted:
                delegate?.locationManager(self, didUpdateLocationPermissions: false)
                /// Resets the location
                currentLocation = nil
            @unknown default: currentLocation = nil
        }
    }
    
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        if let currentLocation = locations.last {
            self.currentLocation = currentLocation
        }
        delegate?.locationManager(self, didUpdateLocations: locations)
    }
    
    func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
        delegate?.locationManager(self, didHeadUpdate: newHeading)
    }
}

extension CLLocation {
    var array: [Double] { return [coordinate.latitude, coordinate.longitude] }
}
