guide/Guibe/MainViewController.swift
2019-06-03 10:52:50 +01:00

412 lines
15 KiB
Swift

//
// MainViewController.swift
// Guibe
//
// Created by Max Hunt on 28/05/2019.
// Copyright © 2019 8. All rights reserved.
//
import UIKit
import AVKit
import MapKit
import CoreLocation
import AVFoundation
class MainViewController: UIViewController, AVAudioPlayerDelegate, myProtocol {
// DELETE
let defaults = UserDefaults.standard
// DELETE
let appDelegate = UIApplication.shared.delegate as! AppDelegate
var etaTime: Int = -1
let locationManager = CLLocationManager()
var currentCoordinate: CLLocationCoordinate2D!
var player = AVAudioPlayer()
var steps = [MKRoute.Step]()
var stepCounter = 0
var previousDistanceToWaypoint: Double = 1000
var distanceToNextCoord: Double = 1000
var startedNavigation: Bool = false
var textSteps: [MKRoute.Step]?
// OUTLETS--------------OUTLETS
@IBOutlet weak var menuWindowView: UIView!
@IBOutlet weak var menuView: UIView!
@IBOutlet weak var menuBtn: UIButton!
@IBOutlet weak var dismissBtn: UIButton!
// ---------------------
@IBOutlet weak var searchBarBg: UIButton!
@IBOutlet weak var searchView: UIView!
@IBOutlet weak var searchBar: UISearchBar!
@IBOutlet weak var micBtn: UIButton!
@IBOutlet weak var keybDismissBtn: UIButton!
// ---------------------
@IBOutlet weak var mapView: MKMapView!
// ---------------------
@IBOutlet weak var etaView: UIView!
@IBOutlet weak var startNaviBtn: UIButton!
@IBOutlet weak var etaLabel: UILabel!
@IBOutlet weak var startNaviImg: UIImageView!
// ---------------------
@IBOutlet weak var cancelBtn: UIButton!
// ---------------------
@IBOutlet weak var persEtaView: UIView!
@IBOutlet weak var persEtaLbl: UILabel!
// OUTLETS--------------OUTLETS
// ACTIONS--------------ACTIONS
@IBAction func menuBtnPressed(_ sender: Any) {
UIView.animate(withDuration: 0.2, animations: {self.menuWindowView.alpha = 1.0})
dismissBtn.isHidden = false
}
@IBAction func micBtnPressed(_ sender: Any) {
}
@IBAction func dismissBtnPressed(_ sender: Any) {
UIView.animate(withDuration: 0.2, animations: {self.menuWindowView.alpha = 0.0})
dismissBtn.isHidden = true
}
@IBAction func settingsBtnPressed(_ sender: Any) {
}
@IBAction func followBtnPressed(_ sender: Any) {
self.mapView.userTrackingMode = .follow
}
@IBAction func headingBtnPressed(_ sender: Any) {
self.mapView.userTrackingMode = .followWithHeading
}
// --------------------------
@IBAction func startNaviPressed(_ sender: Any) {
self.appDelegate.naviStarted = true
self.startedNavigation = true
self.stepCounter += 1
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.searchBar.text = ""
self.etaView.alpha = 0.0
self.searchView.alpha = 0.0
self.cancelBtn.alpha = 1.0
self.persEtaView.alpha = 1.0
}
UIView.animate(withDuration: 0.5, animations: {self.startNaviImg.alpha = 1.0})
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
UIView.animate(withDuration: 0.5, animations: {self.startNaviImg.alpha = 0.0})
}
}
@IBAction func xNaviPressed(_ sender: Any) {
UIView.animate(withDuration: 0.5, animations: {self.etaView.alpha = 0.0})
mapView.removeOverlays(mapView.overlays)
}
@IBAction func cancelBtnPressed(_ sender: Any) {
self.stepCounter = 0
self.startedNavigation = false
self.appDelegate.naviStarted = false
mapView.removeOverlays(mapView.overlays)
UIView.animate(withDuration: 0.3, animations: {
self.searchView.alpha = 1.0
self.cancelBtn.alpha = 0.0
self.persEtaView.alpha = 0.0
})
}
@IBAction func keybDismissBtnPressed(_ sender: Any) {
searchBar.endEditing(true)
self.keybDismissBtn.isHidden = true
}
// --------------------------
// ACTIONS--------------ACTIONS
override func viewDidLoad() {
super.viewDidLoad()
searchBar.delegate = self
searchBarBg.layer.shadowColor = UIColor.black.cgColor
searchBarBg.layer.cornerRadius = 10
searchBarBg.layer.shadowOffset = CGSize(width: 5, height: 7)
searchBarBg.layer.shadowRadius = 10
searchBarBg.layer.shadowOpacity = 0.2
keybDismissBtn.isHidden = true
menuWindowView.alpha = 0.0
menuWindowView.layer.shadowColor = UIColor.black.cgColor
menuWindowView.layer.cornerRadius = 13
menuWindowView.layer.shadowOffset = CGSize(width: 5, height: 7)
menuWindowView.layer.shadowRadius = 10
menuWindowView.layer.shadowOpacity = 0.2
dismissBtn.isHidden = true
mapView.delegate = self
etaView.alpha = 0.0
etaView.layer.shadowColor = UIColor.black.cgColor
etaView.layer.shadowOffset = CGSize(width: 0, height: -10)
etaView.layer.shadowRadius = 10
etaView.layer.shadowOpacity = 0.2
cancelBtn.alpha = 0.0
// cancelBtn.isHidden = true
cancelBtn.layer.shadowColor = UIColor.black.cgColor
cancelBtn.layer.cornerRadius = 15
cancelBtn.layer.shadowOffset = CGSize(width: 3, height: 6)
cancelBtn.layer.shadowRadius = 10
cancelBtn.layer.shadowOpacity = 0.2
startNaviBtn.layer.shadowColor = UIColor.black.cgColor
startNaviBtn.layer.cornerRadius = 13
startNaviBtn.layer.shadowOffset = CGSize(width: 5, height: 7)
startNaviBtn.layer.shadowRadius = 10
startNaviBtn.layer.shadowOpacity = 0.2
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
mapView.userTrackingMode = .follow
startNaviImg.alpha = 0.0
persEtaView.alpha = 0.0
persEtaView.layer.shadowColor = UIColor.black.cgColor
persEtaView.layer.cornerRadius = 7
persEtaView.layer.shadowOffset = CGSize(width: 5, height: 7)
persEtaView.layer.shadowRadius = 7
persEtaView.layer.shadowOpacity = 0.2
} //END OF VIEW DID LOAD
func getDirections(to destination: MKMapItem) {
let sourcePlacemark = MKPlacemark(coordinate: currentCoordinate)
let sourceMapItem = MKMapItem(placemark: sourcePlacemark)
let directionsRequest = MKDirections.Request()
directionsRequest.source = sourceMapItem
directionsRequest.destination = destination
directionsRequest.transportType = .walking
let directions = MKDirections(request: directionsRequest)
directions.calculate { (response, _) in
guard let response = response else { return }
guard let primaryRoute = response.routes.first else { return }
self.mapView.addOverlay(primaryRoute.polyline)
self.steps = primaryRoute.steps
for i in 0 ..< primaryRoute.steps.count {
let step = primaryRoute.steps[i]
// print(step.instructions)
// print(step.distance)
// -----------------------------Geofencing setup
let region = CLCircularRegion(center: step.polyline.coordinate,
radius: 15,
identifier: "\(i)")
// self.locationManager.startMonitoring(for: region)
// -----------------------------Geofencing setup
let circle = MKCircle(center: region.center, radius: region.radius)
self.mapView.addOverlay(circle)
}
let travelTime = Int(primaryRoute.expectedTravelTime/60)
let startDate = Date()
let ETATime = startDate.addingTimeInterval(TimeInterval(travelTime*60))
let ETAVarLbl = DateFormatter.localizedString(from: ETATime, dateStyle: DateFormatter.Style.none, timeStyle: DateFormatter.Style.short)
self.textSteps = primaryRoute.steps
self.appDelegate.textSteps = self.textSteps
self.appDelegate.currentStep = self.stepCounter
// let ivc = self.storyboard?.instantiateViewController(withIdentifier: "ivc") as! InstructionsViewController
// let wivc = WrittenInstructionsViewController()
// wivc.stepBySteps = self.textSteps
// wivc.currentStep = self.stepCounter
// ivc.stepsText = self.textSteps
// ivc.currentStep = self.stepCounter
self.etaLabel.text = "\(ETAVarLbl)"
self.persEtaLbl.text = "\(ETAVarLbl)"
UIView.animate(withDuration: 0.3, animations: {self.etaView.alpha = 1.0})
// self.startedNavigation = true
// self.stepCounter += 1
}
}
func startNavigation(toPlace: MKMapItem){
getDirections(to: toPlace)
}
} //END OF CLASS
extension MainViewController: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let currentLocation = locations.first else { return }
currentCoordinate = currentLocation.coordinate
if startedNavigation == true {
let nextStep = steps[stepCounter]
let nextCoord = CLLocation(latitude: nextStep.polyline.coordinate.latitude, longitude: nextStep.polyline.coordinate.longitude)
distanceToNextCoord = currentLocation.distance(from: nextCoord)
if distanceToNextCoord < previousDistanceToWaypoint {
previousDistanceToWaypoint = currentLocation.distance(from: nextCoord)
}
if distanceToNextCoord > previousDistanceToWaypoint + 10 {
previousDistanceToWaypoint = distanceToNextCoord - 5
playTurnArd()
}
if distanceToNextCoord < 15 {
stepCounter += 1
if stepCounter < steps.count {
// let currentStep = steps[stepCounter]
let message = "\(steps[stepCounter-1].instructions)"
let maneuverCommand = String(message.prefix(10))
switch (maneuverCommand) {
case "Turn right":
playRight()
break;
case "Bear right":
playRight()
break;
case "Turn left ":
playLeft()
break;
case "Bear left":
playLeft()
break;
case "The destin":
playDone()
default:
playErr()
break;
}
// let speechUtterance = AVSpeechUtterance(string: message)
// speechSynthesizer.speak(speechUtterance)
previousDistanceToWaypoint = 1000
} else {
// let speechUtterance = AVSpeechUtterance(string: message)
// speechSynthesizer.speak(speechUtterance)
stepCounter = 0
previousDistanceToWaypoint = 1000
searchBar.isHidden = false
// locationManager.monitoredRegions.forEach({ self.locationManager.stopMonitoring(for: $0) })
}
}
}
}
func playRight(){
// currentStepLbl.text = "COM: RIGHT"
let path = Bundle.main.path(forResource: "xright", ofType : "mp3")!
let url = URL(fileURLWithPath : path)
do {
player = try AVAudioPlayer(contentsOf: url)
player.delegate = self
player.play()
} catch {}
}
func playLeft(){
// currentStepLbl.text = "COM: LEFT"
let path = Bundle.main.path(forResource: "xleft", ofType : "mp3")!
let url = URL(fileURLWithPath : path)
do {
player = try AVAudioPlayer(contentsOf: url)
player.delegate = self
player.play()
} catch {}
}
func playErr(){
// currentStepLbl.text = "COM: ERROR!!!"
return
}
func playTurnArd(){
// currentStepLbl.text = "COM: UTURN"
let path = Bundle.main.path(forResource: "xboth", ofType : "mp3")!
let url = URL(fileURLWithPath : path)
do {
player = try AVAudioPlayer(contentsOf: url)
player.delegate = self
player.play()
} catch {}
}
func playDone(){
// currentStepLbl.text = "COM: DONE"
}
}
extension MainViewController: UISearchBarDelegate {
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
searchBar.endEditing(true) //HIDES LE KEYBOARD
self.keybDismissBtn.isHidden = true
let localSearchRequest = MKLocalSearch.Request()
localSearchRequest.naturalLanguageQuery = searchBar.text
let region = MKCoordinateRegion(center: currentCoordinate, span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1))
localSearchRequest.region = region
let localSearch = MKLocalSearch(request: localSearchRequest)
localSearch.start { (response, _) in
guard let response = response else { return }
let resultsViewController = self.storyboard?.instantiateViewController(withIdentifier: "resultsScreen") as! TableViewController
resultsViewController.searchResults = response.mapItems
resultsViewController.modalTransitionStyle = .coverVertical
resultsViewController.myProtocol = self
self.present(resultsViewController, animated: true, completion: nil)
}
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
self.keybDismissBtn.isHidden = false
}
}
extension MainViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
if overlay is MKPolyline {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = .blue
renderer.alpha = 0.7
renderer.lineWidth = 10
return renderer
}
if overlay is MKCircle {
let renderer = MKCircleRenderer(overlay: overlay)
renderer.strokeColor = .red
renderer.fillColor = .red
renderer.alpha = 0.4
return renderer
}
return MKOverlayRenderer()
}
}