// // PasquakesMapViewController.swift // Earthquake Network // // Created by Andrea Busi on 10/03/21. // Copyright © 2021 Earthquake Network. All rights reserved. // import Foundation import MapKit class PasquakesMapViewController: EQNBaseMapViewController { override var availableFilters: [EQNBaseMapFilter] { [ .oneMonth, .oneWeek, .oneDay, .oneHour ] } // MARK: - Internal /// Pasquakes currently showned on the map private var filteredPastquakes = [EQNPastquakes]() /// Keep track of the evaluated center, to show circles around it private var centerLocation: CLLocation? /// Contains circles drawed on the map private var mapCircles = [MKCircle]() // MARK: - View Lifecycle override func viewDidLoad() { super.viewDidLoad() } // MARK: - Public override func registerMapAnnotationViews() { mapView.register(EQNCustomAnnotationView.self, forAnnotationViewWithReuseIdentifier: EQNCustomAnnotationView.SingleLineIdentifier) } override func loadDataSource() { guard let list = EQNManager.manager().datiPastQuakes else { return } // set the base filter setDefaultFilter(for: list) // filter report based on selected filter let filterDate = filter.date filteredPastquakes = list.filter { $0.date > filterDate } // create annotations to display on the map let annotations = filteredPastquakes.compactMap { EQNMapAnnotationPastquake(pastquake: $0) } // elaborate the center centerLocation = elaborateCenter(for: filteredPastquakes) // update map and center updateMap(with: annotations) if let centerLocation = centerLocation { addCircles(for: centerLocation) } } override func elaborateMapCenter() { guard let centerLocation = centerLocation else { return } setMapCenter(for: centerLocation) } override func didTapAnnotation(_ annotation: MKAnnotation) { mapView.deselectAnnotation(annotation, animated: true) guard let annotation = annotation as? EQNMapAnnotationPastquake, let pastquake = annotation.pastquake else { return } let difference = Int(Date().timeIntervalSince(pastquake.date) / 60.0) let title = EQNUtility.formattedString(forTimeDifference: difference) let message = "" + "📱 " + String(format: NSLocalizedString("map_number", comment: ""), "\(pastquake.users)") + "\n⏱ " + EQNUtility.formattedDate(from: pastquake.date) + " \(NSLocalizedString("share_yourtime", comment: ""))" let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) alert.addAction(UIAlertAction(title: NSLocalizedString("official_close", comment: ""), style: .cancel, handler: nil)) present(alert, animated: true, completion: nil) } // MARK: - Private private func elaborateCenter(for pastquakes: [EQNPastquakes]) -> CLLocation? { var center: CLLocation? // Se c'è un rilevamento distante dall'utente meno del raggio di notifica, // allora il centro è su quel rilevamento if let userPosition = CLLocationManager().location { let nearestPastquake = filteredPastquakes .sorted(by: { (pastquake1, pastquake2) -> Bool in abs(userPosition.distance(from: pastquake1.coordinate)) < abs(userPosition.distance(from: pastquake2.coordinate)) }) .first // controlliamo che sia inferiore al raggio massimo impostato per le notifiche if let radiusLow = Double(EQNSettingRealTimeAlert.shared.raggioSismiLievi), let radiusStrong = Double(EQNSettingRealTimeAlert.shared.raggioSismiForti), let nearestPastquake = nearestPastquake { let radius = max(radiusLow, radiusStrong) if abs(nearestPastquake.coordinate.distance(from: userPosition)) < radius { center = nearestPastquake.coordinate } } } // altrimenti il centro è sul rilevamento più recente if center == nil, let newestPastquake = filteredPastquakes.sorted(by: { $0.date > $1.date }).first { center = newestPastquake.coordinate } return center } private func addCircles(for location: CLLocation) { // aggiungiamo 3 cerchi concentrici per il punto specificato // li inseriamo a a 50, 100 e 200 km. let circles = [ MKCircle(center: location.coordinate, radius: 25_000), MKCircle(center: location.coordinate, radius: 100_000), MKCircle(center: location.coordinate, radius: 200_000) ] // elimino vecchie circonferenze mapView.removeOverlays(mapCircles) // !!note: is important to assign here the circles // otherwise `addOverlays` will not work mapCircles = circles // creo nuovi cerchi mapView.addOverlays(circles) } // MARK: - Map override func setupAnnotationView(for annotation: MKAnnotation, on mapView: MKMapView) -> MKAnnotationView? { guard let annotation = annotation as? EQNMapAnnotationPastquake else { return nil } let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: EQNCustomAnnotationView.SingleLineIdentifier, for: annotation) as! EQNCustomAnnotationView annotationView.image = annotation.image annotationView.title = annotation.title return annotationView } func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer { guard let circleOverlay = overlay as? MKCircle else { return MKOverlayRenderer(overlay: overlay) } let circle = MKCircleRenderer(overlay: circleOverlay) circle.strokeColor = AppTheme.Colors.darkGray circle.lineWidth = 1.0 return circle } }