// // NotificationViewController.m // EQNNotificationContent // // Refactored by Andrea Busi on 14/10/2020. // Copyright © 2020 Earthquake Network. All rights reserved. // #import "NotificationViewController.h" #import "PastquakesAnnotation.h" #import "ReteSismicaAnnotation.h" #import "EQNUtility.h" @import UserNotifications; @import UserNotificationsUI; @import MapKit; @interface NotificationViewController () @property (weak, nonatomic) IBOutlet UILabel *titleLabel; @property (weak, nonatomic) IBOutlet UILabel *descriptionLabel; @property (weak, nonatomic) IBOutlet UILabel *waveLabel; @property (weak, nonatomic) IBOutlet MKMapView *mapView; /// This will be calculated as seismic date + warning time @property (strong, nonatomic) NSDate *userSeismicTimestamp; @property (strong, nonatomic) NSTimer *countdownTimer; @end @implementation NotificationViewController - (void)setMapView:(MKMapView *)mapView { _mapView = mapView; _mapView.scrollEnabled = NO; _mapView.zoomEnabled = NO; } #pragma mark - View Lifecycle - (void)viewDidLoad { [super viewDidLoad]; // Do any required interface initialization here. } - (void)didReceiveNotification:(UNNotification *)notification { UNNotificationContent *content = notification.request.content; NSDictionary *userInfo = content.userInfo; // set title and description self.titleLabel.text = content.title; self.descriptionLabel.text = content.body; // add annotation onthe map CLLocation *coordinate = [[CLLocation alloc] initWithLatitude:[userInfo[@"latitude"] doubleValue] longitude:[userInfo[@"longitude"] doubleValue]]; MKCoordinateSpan span = MKCoordinateSpanMake(10.5, 10.5); MKCoordinateRegion region = MKCoordinateRegionMake(coordinate.coordinate, span); [self.mapView setCenterCoordinate:coordinate.coordinate animated:NO]; [self.mapView setRegion:region animated:YES]; if ([userInfo[@"type"] isEqualToString:@"eqn"]) { PastquakesAnnotation *annotation = [[PastquakesAnnotation alloc] initWithTitle:content.body location:coordinate.coordinate intensita:[userInfo[@"intensity"] intValue]]; [self.mapView addAnnotation:annotation]; } else if ([userInfo[@"type"] isEqualToString:@"manual"]){ ReteSismicaAnnotation *annotation = [[ReteSismicaAnnotation alloc] initWithTitle:content.body location:coordinate.coordinate magnitudo:[userInfo[@"magnitudo"] intValue]]; [self.mapView addAnnotation:annotation]; } self.userSeismicTimestamp = [self calculateUserSeismicTimestampWithInfo:userInfo]; if (self.userSeismicTimestamp) { // start the countdown self.countdownTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(countdownFired:) userInfo:nil repeats:YES]; [self.countdownTimer fire]; } } #pragma mark - Private - (nullable NSDate *)calculateUserSeismicTimestampWithInfo:(NSDictionary *)info { // dobbiamo calcolare l'ora in cui il sisma arriverà nella posizione dell'utente // per fare questo, il calcolo sarà: // timestamp sisma + warning time // ultima posizione nota dell'utente CLLocationManager *manager = [[CLLocationManager alloc] init]; CLLocation *lastUserLocation = manager.location; if (!lastUserLocation) { return nil; } // posizione sisma double latitude = [info[@"latitude"] doubleValue]; double longitude = [info[@"longitude"] doubleValue]; CLLocation *location = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude]; // distanza tra sisma e utente (in km) CLLocationDistance distance = [lastUserLocation distanceFromLocation:location]; double userDistance = distance/1000; // calcoliamo warning_time double waveSpeed = [info[@"wave_speed"] doubleValue]; double warningTime = round(userDistance/waveSpeed - 5); // aggiungiamo il warning time al timestamp del sisma NSDate *seismicDate = [EQNUtility getDateFromString:info[@"datetime"]]; NSDate *userSeismicDate = [seismicDate dateByAddingTimeInterval:warningTime]; return userSeismicDate; } - (void)countdownFired:(id)sender { NSDate *now = [NSDate date]; NSTimeInterval difference = MAX([self.userSeismicTimestamp timeIntervalSinceDate:now], 0); self.waveLabel.text = [NSString stringWithFormat:@"%@ %.0f %@", NSLocalizedString(@"alert_wave", @""), difference, NSLocalizedString(@"alert_seconds", @"")]; if (difference <= 0) { // stop the countdown [self.countdownTimer invalidate]; self.countdownTimer = nil; } } #pragma mark - MKMapViewDelegate - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation { if ([annotation isKindOfClass:[PastquakesAnnotation class]]) { PastquakesAnnotation *anLocation = (PastquakesAnnotation *)annotation; MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:IDENTIFIER_ANNOTATION_PASTQUAKES]; if (annotationView == nil) { annotationView = anLocation.annotationView; } else { annotationView.annotation = anLocation; } return annotationView; } else if ([annotation isKindOfClass:[ReteSismicaAnnotation class]]) { ReteSismicaAnnotation *anLocation = (ReteSismicaAnnotation *)annotation; MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:IDENTIFIER_ANNOTATION_RETESMARTPHONE]; if (annotationView == nil) { annotationView = anLocation.annotationView; } else { annotationView.annotation = anLocation; } return annotationView; } return nil; } @end