//
//  ViewController.swift
//  MapApp2
//
//  Created by Alison O'Connor on 9/16/15.
//  Copyright © 2015 Alison O'Connor. All rights reserved.
//
// $GPRMC,064951.000,A,4141.1456,N,08614.4338,E,0.03,165.48,260406,3.05,W,A*2C

// Done: save/show last location, customize annotations
// To do: notifications


import UIKit
import MapKit
import CoreLocation
import CoreMotion
import CocoaMQTT
import Foundation

class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate{
 
    var onOff: String! = "Tracker Off"
    var lastOnOff:String! = "Last Off"
    var window: UIWindow?
    var timeOfDay: String!
    var timeHourDouble: Int!
   
    var info1 = Annotation()
    var info2 = Annotation()
    
    var found:Bool = true


   
    
   @IBOutlet weak var foundButton: UIButton!
   
   @IBAction func foundButton(sender: AnyObject) {
      foundWarn()
   }
    
   
    @IBOutlet weak var resetButton: UIButton!
    
    @IBAction func resetButton(sender: AnyObject) {
        self.mqtt!.publish("bikeMQTT6/inTopic", withString: "Bike Found", qos: .QOS1)
    }
    
    
    @IBOutlet weak var foundBackground: UITextField!
    
    @IBOutlet weak var timeText: UITextView!
   
    @IBOutlet weak var segmentedControl2: UISegmentedControl!
    
    @IBOutlet weak var mapView: MKMapView!
    @IBOutlet weak var waitBox: UITextView!
    @IBOutlet weak var segmentedControl: UISegmentedControl!
    @IBAction func segmentedControlAction(sender: AnyObject) {
        switch segmentedControl.selectedSegmentIndex
        {
        case 0:
            onOff = "Tracker On"
            self.waitBox.hidden = false
         
        case 1:
            onOff = "Tracker Off"
            waitBox.hidden = true
            
        default:
            break;
        }
        //mqtt!.publish("bikeMQTT/inTopic", withString: onOff, qos: .QOS1)
    }
    
    @IBAction func segmentedControl2Action(sender: AnyObject) {
        
        switch segmentedControl2.selectedSegmentIndex{
        
        case 0:
         
            lastOnOff = "Last On"
            
            let defaults = NSUserDefaults.standardUserDefaults()
        
            let lastTime = defaults.stringForKey("StartTime")
        
            self.timeText.text = "Last Updated: " + lastTime!
        
            timeText.hidden = false
        
            print(lastTime)
            
            let lastLongitude = defaults.stringForKey("StartLongitude")
            let lastLatitude = defaults.stringForKey("StartLatitude")
        
            let lastLongDoub = Double(lastLongitude!)
            let lastLatDoub = Double(lastLatitude!)
        
            print(lastLongDoub)
            print(lastLatDoub)
        
            if (lastLongDoub != nil){
            
               let location = CLLocationCoordinate2D(
                     latitude: lastLatDoub!,
                     longitude: lastLongDoub!
               )

            info2.coordinate = location
            info2.color = .Purple
            
            mapView.addAnnotation(info2)
               
        }
        
        case 1:
            lastOnOff = "Last Off"
            mapView.removeAnnotation(info2)
        
        default:
        break
        }
        
    }
    
    
    var mqtt: CocoaMQTT?
    
    let locationManager = CLLocationManager()
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        foundBackground.hidden = true
        foundButton.hidden = true
        
        waitBox.hidden = true
      
        timeText.hidden = true

        mapView.mapType = MKMapType.Hybrid
        let mapCenter = CLLocationCoordinate2D(
            latitude: 41.701564,
            longitude: -86.237426
        )
        let span = MKCoordinateSpanMake(0.03, 0.03)
        let region = MKCoordinateRegion(center:  mapCenter, span: span)
        self.mapView.setRegion(region, animated: true)

        
        navigationController?.interactivePopGestureRecognizer?.enabled = false
        mqttSetting()
        mqtt!.connect()
        
        self.mapView.delegate = self
        //self.locationManager.delegate = self


    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    func mqttSetting() {
        mqtt = CocoaMQTT(clientId: "BikeTracker", host: "senior-mqtt.esc.nd.edu", port: 1883)
        //senior-mqtt.esc.nd.edu    10.176.58.5
        if let mqtt = mqtt {
            mqtt.username = "test"
            mqtt.password = "public"
            mqtt.willMessage = CocoaMQTTWill(topic: "/will", message: "dieout")
            mqtt.keepAlive = 90
            mqtt.delegate = self
        }
    }

    //Get current location
    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        
        let location = locations.last
        let currentCords = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
        let currentLocation = MKPointAnnotation()
        currentLocation.coordinate = currentCords
        
        self.locationManager.stopUpdatingLocation()
        
    }
    
    func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
        print("Error: " + error.localizedDescription)
    }
    
    //Stop updating location/motion when closed
    override func viewDidDisappear(animated: Bool) {
        super.viewDidDisappear(animated)
        
        if CLLocationManager.locationServicesEnabled() {
            locationManager.stopUpdatingLocation()
        }
        
    }

    
    func moveWarn() {
        var notification = UILocalNotification()
        notification.alertBody = "Your Bike is Moving" // text that will be displayed in the notification
        notification.alertAction = "open" // text that is displayed after "slide to..." on the lock screen - defaults to "slide to view"
        notification.soundName = UILocalNotificationDefaultSoundName // play default sound
        notification.fireDate = NSDate(timeIntervalSinceNow: 5)
        UIApplication.sharedApplication().applicationIconBadgeNumber = 0
        UIApplication.sharedApplication().scheduleLocalNotification(notification)
        
        let cheerText = ("Your Bike is Moving")
        let messager = ("The Track Map will update shortly")
        let alert = UIAlertController(title: cheerText, message: messager, preferredStyle: UIAlertControllerStyle.Alert)
        alert.addAction(UIAlertAction(title: "Close", style: UIAlertActionStyle.Default, handler: nil))
        self.presentViewController(alert, animated: true, completion: nil)

    }
   
   func foundWarn() {
      let cheerText = ("Hooray!")
      let messager = ("You Found Your Bike")
      let alert = UIAlertController(title: cheerText, message: messager, preferredStyle: UIAlertControllerStyle.Alert)
      alert.addAction(UIAlertAction(title: "Oops! My Bike is Still Lost!", style: .Default, handler: nil))
      alert.addAction(UIAlertAction(title: "Return to Normal Track Mode", style: .Cancel, handler: { action in
         switch action.style{
         case .Default:
            print("default")
            
         case .Cancel:
            let found = true
            self.foundBackground.hidden = true
            self.foundButton.hidden = true
            self.mqtt!.publish("bikeMQTT6/inTopic", withString: "Bike Found", qos: .QOS1)
         
         case .Destructive:
            print("destructive")
            
         }
      }))
      
      
      self.presentViewController(alert, animated: true, completion: nil)
      
   }


   
    func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
        if (annotation is MKUserLocation) {
            return nil
        }
        
        let reuseId = "pin"
        var anView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
        if anView == nil {
            if let anAnnotation = annotation as? Annotation {
                    let pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
                    pinView.pinColor = anAnnotation.color
                    anView = pinView
            }
            anView!.canShowCallout = false
        }
        else {
            anView!.annotation = annotation
        }
        
        return anView
    }
   
}

class Annotation: NSObject, MKAnnotation
{
    var coordinate: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)
    var color: MKPinAnnotationColor = .Red
}


extension Double {
    func format(f: String) -> String {
        return String(format: "%\(f)f", self)
    }
    func roundToPlaces(places:Int) -> Double {
      let divisor = pow(10.0, Double(places))
      return round(self * divisor) / divisor
   }
}

extension MapViewController: CocoaMQTTDelegate {
    
    func mqtt(mqtt: CocoaMQTT, didConnect host: String, port: Int) {
        print("didConnect \(host):\(port)")
      
        if (onOff == "Tracker On"){
            self.waitBox.hidden = false
            self.waitBox.text = "Looking for GPS location..."
            self.waitBox.backgroundColor = .whiteColor()
            self.waitBox.textColor = .blackColor()
            self.waitBox.font = UIFont (name: "Helvetica Neue", size: 16.0)
            self.waitBox.textAlignment = .Center
      }
    }
   
    func mqtt(mqtt: CocoaMQTT, didConnectAck ack: CocoaMQTTConnAck) {
        if ack == .ACCEPT {
            mqtt.subscribe("bikeMQTT6/+", qos: CocoaMQTTQOS.QOS1)
            mqtt.ping()
            
        }
        
    }
    
    func mqtt(mqtt: CocoaMQTT, didPublishMessage message: CocoaMQTTMessage, id: UInt16) {
        print("didPublishMessage with message: \(message.string)")
    }
    
    func mqtt(mqtt: CocoaMQTT, didPublishAck id: UInt16) {
        print("didPublishAck with id: \(id)")
    }
    
    func mqtt(mqtt: CocoaMQTT, didReceiveMessage message: CocoaMQTTMessage, id: UInt16 ) {
        
        print("didReceiveMessage: \(message.string) with id \(message.topic)")
      
      if (message.string != nil){

      
        if (lastOnOff == "Last On"){
         
            mapView.removeAnnotation(info2)
         
            let defaults = NSUserDefaults.standardUserDefaults()
            let lastLongitude = defaults.stringForKey("StartLongitude")
            let lastLatitude = defaults.stringForKey("StartLatitude")
         
            let lastLongDoub = Double(lastLongitude!)
            let lastLatDoub = Double(lastLatitude!)
         
            print(lastLongDoub!)
            print(lastLatDoub!)
         
            if (lastLongDoub != nil){
            
               let location = CLLocationCoordinate2D(
                  latitude: lastLatDoub!,
                  longitude: lastLongDoub!
               )
            
               info2.coordinate = location
               info2.color = .Purple
            
               mapView.addAnnotation(info2)
            }
         
        }
      
      
       if (message.string!.hasPrefix("hello world")){
             mqtt.publish("bikeMQTT6/inTopic", withString: onOff, qos: .QOS2)
       }
      
      
         
        if (onOff == "Tracker On"){
         
         if (message.string != nil){         
         
            if (message.string!.hasPrefix("Activity!")){
                    self.moveWarn()
                    let found = false;
                    foundBackground.hidden = false
                    foundButton.hidden = false
               
                }
            
            
            if (message.string!.hasPrefix("$GPRMC")){
               
                    self.mapView.removeAnnotation(info1)

                    let gpsArray = [Character](message.string!.characters)
               
                    if (gpsArray[18] == "A"){
                        
                        let latitudeDeg = gpsArray[20...21]
                        let latitudeMin = gpsArray[22...28]
                        
                        let latDegString = String(latitudeDeg)
                        let latMinString = String(latitudeMin)
                        
                        let latDegDouble = Double(latDegString)
                        let latMinDouble = Double(latMinString)
                        
                        let latMinDoubleMod = Double(latMinDouble! / 60)
                        
                        let newLatitude = latDegDouble! + latMinDoubleMod
                        
                        print(latDegDouble!)
                        print(latMinDoubleMod)
                        
                        let longitudeDeg = gpsArray[32...34]
                        let longitudeMin = gpsArray[35...41]
                        
                        let longDegString = String(longitudeDeg)
                        let longMinString = String(longitudeMin)
                        
                        let longDegDouble = Double(longDegString)
                        let longMinDouble = Double(longMinString)
                        
                        let longMinDoubleMod = Double(longMinDouble! / 60)
                        
                        print(longDegString)
                        print(longMinDoubleMod)
                        
                        let newLongitude = -(longDegDouble! + longMinDoubleMod)
                     
                        print(newLatitude)
                        print(newLongitude)
                        
                        
                        let defaults = NSUserDefaults.standardUserDefaults()
                        defaults.setObject(newLongitude, forKey: "StartLongitude")
                        defaults.synchronize()
                        defaults.setObject(newLatitude, forKey: "StartLatitude")
                        defaults.synchronize()
                     
                        waitBox.hidden = true
                        
                        // Get Current Location
                        self.locationManager.delegate = self
                        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
                        self.locationManager.requestWhenInUseAuthorization()
                        self.locationManager.startUpdatingLocation()
                        self.mapView.showsUserLocation = true
                        
                        // Set Bike Location
                        let location = CLLocationCoordinate2D(
                            latitude: newLatitude,
                            longitude: newLongitude
                        )
                     
                        self.mapView.showsUserLocation = true

                        
                        info1.coordinate = location
                        info1.color = .Green
                     
                        mapView.addAnnotation(info1)
                     
                        let timeHour = gpsArray[7...8]
                        let timeMinute = gpsArray[9...10]
                        let timeSecond = gpsArray[11...12]

                        let timeHourString = String(timeHour)
                        let timeMinString = String(timeMinute)
                        let timeSecString = String(timeSecond)
                        //print(timeString)
                     
                        let timeHourDoubleOrig = Int(timeHourString)
                        timeHourDouble = timeHourDoubleOrig! - 4
                        if timeHourDouble < 12 {
                           timeOfDay = "AM"
                        } else {
                           timeOfDay = "PM"
                           if (timeHourDouble != 12) {
                           timeHourDouble = timeHourDouble! - 12
                           }
                        }
                     
                        let timeHourStringMod = String(timeHourDouble)
                     
                        self.timeText.text = "Last Updated: " + timeHourStringMod + ":" + timeMinString + ":" + timeSecString + " " + timeOfDay
                     
                        let timeString = timeHourStringMod + ":" + timeMinString + ":" + timeSecString + " " + timeOfDay
                     
                        print(timeString)
                        timeText.hidden = false
                     
                        defaults.setObject(timeString, forKey: "StartTime")
                        defaults.synchronize()
                     
                        } else {
                     
                           self.waitBox.hidden = false
                           self.waitBox.text = "Waiting for GPS Location..."
                           self.waitBox.font = UIFont (name: "Helvetica Neue", size: 16.0)
                           self.waitBox.textAlignment = .Center
                     
                           self.waitBox.backgroundColor = UIColor.whiteColor()
                           self.waitBox.textColor = UIColor.blackColor()
                           self.mapView.showsUserLocation = false
                           
                           
                        }
                  }
         
         
            } else if (onOff == "Tracker Off"){
            
                self.mapView.showsUserLocation = false
                self.mapView.removeAnnotation(info1)
                waitBox.hidden = true
            }
      }
   }
   }
   
    
    
    func mqtt(mqtt: CocoaMQTT, didSubscribeTopic topic: String) {
        print("didSubscribeTopic to \(topic)")
    }
    
    func mqtt(mqtt: CocoaMQTT, didUnsubscribeTopic topic: String) {
        print("didUnsubscribeTopic to \(topic)")
    }
    
    func mqttDidPing(mqtt: CocoaMQTT) {
        print("didPing")
    }
    
    func mqttDidReceivePong(mqtt: CocoaMQTT) {
        _console("didReceivePong")
    }
    
    func mqttDidDisconnect(mqtt: CocoaMQTT, withError err: NSError?) {
        _console("mqttDidDisconnect")
      
        if (onOff == "Tracker On"){
           self.waitBox.hidden = false
           self.waitBox.text = "Connecting to Server..."
           self.waitBox.font = UIFont (name: "Helvetica Neue", size: 16.0)
           self.waitBox.textAlignment = .Center
           self.waitBox.backgroundColor = UIColor(red: 242/255, green: 38/255, blue: 19/255, alpha: 1.0)
           self.waitBox.textColor = .whiteColor()
      }
           self.mqtt!.connect()
      
    }
    
    func _console(info: String) {
        print("Delegate: \(info)")
    }
    
}
