// // SeismicNetworksViewController.swift // Earthquake Network // // Created by Busi Andrea on 22/09/2020. // Copyright © 2020 Earthquake Network. All rights reserved. // import UIKit import EventKitUI import DZNEmptyDataSet class SeismicNetworksViewController: EQNBaseViewController, UITableViewDelegate, UITableViewDataSource { private static let SegueIdentifierMap = "ShowMapDetail" private static let SegueIdentifierFilters = "ShowFilters" private static let SegueIdentifierSettings = "ShowSettings" private static let SegueIdentifierSeismicNetworks = "ShowSeismicNetworks" private static let SegueIdentifierCardSettings = "ShowCardSettings" // MARK: - Internal @IBOutlet private weak var tableView: UITableView? @IBOutlet private weak var expandeCollapseButton: UIBarButtonItem! /// Seismisc to display private var seismics = [EQNSisma]() /// Informations to display on a single cell private var informations = [SeismicNetworkTableViewCell.InformationType]() /// Index path of row with map expanded private var openMapIndexPath: IndexPath? /// Index path of row with weather expanded private var openWeatherIndexPath: IndexPath? // MARK: - View Lifecycle override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(didReceiveDownloadCompletedNotification(_:)), name: NSNotification.Name(rawValue: NOTIFICA_DOWNLOAD_TERMINATO), object: nil) setupUI() refreshUI() // only the first time, show the popup for country selection let alreadyPresented = UserDefaults.standard.bool(forKey: EQNUserDefaultKeyOneShotShowCountry) if !alreadyPresented { performSegue(withIdentifier: Self.SegueIdentifierSettings, sender: nil) UserDefaults.standard.setValue(true, forKey: EQNUserDefaultKeyOneShotShowCountry) } } private func setupUI() { title = NSLocalizedString("tab_official", comment: "") tableView?.estimatedRowHeight = 300.0; tableView?.rowHeight = UITableView.automaticDimension tableView?.register(SeismicNetworkTableViewCell.self, forCellReuseIdentifier: SeismicNetworkTableViewCell.Identifier) tableView?.emptyDataSetSource = self } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { switch segue.identifier { case Self.SegueIdentifierMap: if let seismic = sender as? EQNSisma, let navController = segue.destination as? UINavigationController, let controller = navController.viewControllers.first as? ReteSismiDettagliMappa { controller.sisma = seismic } case Self.SegueIdentifierFilters: if let controller = segue.destination as? SeismicFiltersViewController { controller.delegate = self } case Self.SegueIdentifierSettings: if let controller = segue.destination as? SeismicSettingsViewController { controller.delegate = self } case Self.SegueIdentifierSeismicNetworks: if let navController = segue.destination as? UINavigationController, let controller = navController.viewControllers.first as? SeismicSettingsNetworksViewController { controller.delegate = self } case Self.SegueIdentifierCardSettings: if let controller = segue.destination as? SeismicCardSettingsViewController { controller.delegate = self } default: break } } // MARK: - Notification @objc func didReceiveDownloadCompletedNotification(_ notification: NSNotification) { DispatchQueue.main.async { self.openMapIndexPath = nil self.openWeatherIndexPath = nil self.refreshUI() } } // MARK: - Private override func refreshUI() { super.refreshUI() let allSeismics = EQNManager.manager().retiSismiche seismics = EQNSeismic.shared.filterSeismicList(allSeismics ?? []) if let saved = UserDefaults.standard.array(forKey: EQNUserDefaultKeySesmicInformations) as? [Int] { informations = saved.compactMap { SeismicNetworkTableViewCell.InformationType(rawValue: $0) } } if informations.contains(.buttons) { expandeCollapseButton.image = UIImage(named: "navbar-icon-arrow-collapse") } else { expandeCollapseButton.image = UIImage(named: "navbar-icon-arrow-expand") } tableView?.reloadData() } // MARK: - Actions @IBAction func refreshDataTapped(_ sender: Any) { EQNManager.manager().sincronizza() } @IBAction func openFilterTapped(_ sender: Any) { performSegue(withIdentifier: Self.SegueIdentifierFilters, sender: nil) } @IBAction func openSettingsTapped(_ sender: Any) { performSegue(withIdentifier: Self.SegueIdentifierSettings, sender: nil) } @IBAction func collapseExpandTapped(_ sender: Any) { if informations.contains(.buttons) { informations.removeAll(where: { $0 == .buttons }) } else { informations.append(.buttons) } UserDefaults.standard.set(informations.map { $0.rawValue }, forKey: EQNUserDefaultKeySesmicInformations) refreshUI() } // MARK: - Table view delegate and data source func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { seismics.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: SeismicNetworkTableViewCell.Identifier, for: indexPath) as! SeismicNetworkTableViewCell let seismic = seismics[indexPath.row] var type = SeismicNetworkTableViewCell.DisplayType.normal if openMapIndexPath == indexPath { type = .mapExpanded } else if openWeatherIndexPath == indexPath { type = .weatherExpanded } cell.configure(with: seismic, type: type, informations: informations) cell.delegate = self return cell } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) let seismic = seismics[indexPath.row] performSegue(withIdentifier: Self.SegueIdentifierMap, sender: seismic) } // MARK: - Private private func openCalendar(for seismic: EQNSisma) { checkCalendarPermission { self.createCalendarEvent(for: seismic) } failure: { let alert = UIAlertController(title: NSLocalizedString("Attenzione", comment: ""), message: "Non è possibile aprire il calendario, assicurarsi di aver impostato i permessi corretti", preferredStyle: .alert) alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default)) self.present(alert, animated: true) } } private func checkCalendarPermission(success: @escaping () -> Void, failure: @escaping () -> Void) { let authorization = EKEventStore.authorizationStatus(for: .event) switch authorization { case .notDetermined: let eventStore = EKEventStore() eventStore.requestAccess(to: .event) { (granted, error) in DispatchQueue.main.async { if granted { success() } else { failure() } } } case .authorized: success() default: failure() } } private func createCalendarEvent(for seismic: EQNSisma) { let eventStore = EKEventStore() // calendar event let event = EKEvent(eventStore: eventStore) event.title = seismic.place event.startDate = seismic.date event.endDate = seismic.date event.notes = String(format: NSLocalizedString("calendar_description_nogeo_km", comment: ""), seismic.magnitude, seismic.depth) // controller to present let eventVC = EKEventEditViewController() eventVC.editViewDelegate = self eventVC.eventStore = eventStore eventVC.event = event present(eventVC, animated: true) } } extension SeismicNetworksViewController: SeismicNetworkTableViewCellDelegate { func seismicNetworkCellDidTapShare(_ cell: SeismicNetworkTableViewCell) { guard let index = tableView?.indexPath(for: cell) else { return } // create a snapshot of the cell and share with default share sheet let snapshot = cell.createSnapshot() // text to share with the snapshot let seismic = seismics[index.row] let shareHashtag = NSLocalizedString("share_hashtag", comment: "") let magnitude = String(format: "%.1f", seismic.magnitude.doubleValue) let location = seismic.place let notified = NSLocalizedString("share_notified", comment: "") let shareMessage = "\(shareHashtag) M\(magnitude), \(location). \(notified)" let controller = UIActivityViewController(activityItems: [snapshot, shareMessage], applicationActivities: []) present(controller, animated: true) } func seismicNetworkCellDidTapWeather(_ cell: SeismicNetworkTableViewCell) { guard let index = tableView?.indexPath(for: cell) else { return } let indexToReloads = [openMapIndexPath, openWeatherIndexPath, index].compactMap { $0 } openWeatherIndexPath = index openMapIndexPath = nil tableView?.reloadRows(at: indexToReloads, with: .automatic) } func seismicNetworkCellDidTapMap(_ cell: SeismicNetworkTableViewCell) { guard let index = tableView?.indexPath(for: cell) else { return } let indexToReloads = [openMapIndexPath, openWeatherIndexPath, index].compactMap { $0 } openMapIndexPath = index openWeatherIndexPath = nil tableView?.reloadRows(at: indexToReloads, with: .automatic) } func seismicNetworkCellDidTapMapDetail(_ cell: SeismicNetworkTableViewCell) { guard let index = tableView?.indexPath(for: cell) else { return } let seismic = seismics[index.row] performSegue(withIdentifier: Self.SegueIdentifierMap, sender: seismic) } func seismicNetworkCellDidTapCalendar(_ cell: SeismicNetworkTableViewCell) { guard let index = tableView?.indexPath(for: cell) else { return } let seismic = seismics[index.row] openCalendar(for: seismic) } func seismicNetworkCellDidTapSettings(_ cell: SeismicNetworkTableViewCell) { performSegue(withIdentifier: Self.SegueIdentifierCardSettings, sender: nil) } func seismicNetworkCellDidTapClose(_ cell: SeismicNetworkTableViewCell) { guard let index = tableView?.indexPath(for: cell) else { return } let indexToReloads = [openMapIndexPath, openWeatherIndexPath, index].compactMap { $0 } openMapIndexPath = nil openWeatherIndexPath = nil tableView?.reloadRows(at: indexToReloads, with: .automatic) } } extension SeismicNetworksViewController: EKEventEditViewDelegate { func eventEditViewController(_ controller: EKEventEditViewController, didCompleteWith action: EKEventEditViewAction) { dismiss(animated: true, completion: nil) } } extension SeismicNetworksViewController: SeismicFiltersViewControllerDelegate { func seismicFiltersControllerDidUpdateFilters(_ controller: SeismicFiltersViewController) { if controller.needsDataUpdate { EQNManager.manager().sincronizza() } refreshUI() } } extension SeismicNetworksViewController: SeismicSettingsViewControllerDelegate { func seismicSettingsControllerDidComplete(_ controller: SeismicSettingsViewController) { refreshUI() } func seismicSettingsControllerWillOpenProviders(_ controller: SeismicSettingsViewController) { performSegue(withIdentifier: Self.SegueIdentifierSeismicNetworks, sender: nil) } } extension SeismicNetworksViewController: SeismicSettingsNetworksViewControllerDelegate { func seismicSettingsNetworksControllerDidComplete(_ controller: SeismicSettingsNetworksViewController) { refreshUI() } } extension SeismicNetworksViewController: SeismicCardSettingsViewControllerDelegate { func seismicCardSettingsDidComplete(_ controller: SeismicCardSettingsViewController) { refreshUI() } } extension SeismicNetworksViewController: DZNEmptyDataSetSource { func title(forEmptyDataSet scrollView: UIScrollView!) -> NSAttributedString! { let attributes = [ NSAttributedString.Key.font: UIFont.preferredFont(forTextStyle: .body) ] let string = NSAttributedString(string: NSLocalizedString("filter_empty", comment: ""), attributes: attributes) return string } }