<commit_before>//
//  NetworkManager.swift
//  GSR
//
//  Created by <NAME> on 01/02/2018.
//  Copyright © 2016 <NAME>. All rights reserved.
//

import Foundation
import SwiftyJSON

class GSRNetworkManager: NSObject, Requestable {
    
    static let instance = GSRNetworkManager()
    
    let availUrl = "https://api.pennlabs.org/studyspaces/availability"
    let locationsUrl = "https://api.pennlabs.org/studyspaces/locations"
    let bookingUrl = "https://api.pennlabs.org/studyspaces/book"
    let reservationURL = "https://api.pennlabs.org/studyspaces/reservations"
    let cancelURL = "https://api.pennlabs.org/studyspaces/cancel"
    
    var locations:[Int:String] = [:]
    var bookingRequestOutstanding = false
    
    
    func getLocations (callback: @escaping (([Int:String]?) -> Void)) {
        let url = locationsUrl
        getRequest(url: url) { (dict, error, statusCode) in
            if let dict = dict {
                let json = JSON(dict)
                self.locations = self.parseLocations(json: json)
                callback(self.locations)
            } else {
                callback(nil)
            }
        }
    }
    
    func getAvailability(for gsrId: Int, date: GSRDate, callback: @escaping ((_ rooms: [GSRRoom]?) -> Void)) {
        self.getAvailability(for: gsrId, dateStr: date.string) { (rooms) in
            callback(rooms)
        }
    }

    func getAvailability(for gsrId: Int, dateStr: String, callback: @escaping ((_ rooms: [GSRRoom]?) -> Void)) {
        var url = "\(availUrl)/\(gsrId)?date=\(dateStr)"
        if let sessionID = GSRUser.getSessionID() {
            url = "\(url)&sessionid=\(sessionID)"
        }
        getRequest(url: url) { (dict, error, statusCode) in
            var rooms: [GSRRoom]!
            if let dict = dict {
                let json = JSON(dict)
                rooms = Array<GSRRoom>(json: json)
            }
            
            if statusCode == 400 && gsrId == 1 {
                // If Session ID invalid, clear it and try again without one
                GSRUser.clearSessionID()
                self.getAvailability(for: gsrId, dateStr: dateStr, callback: callback)
                return
            }
            callback(rooms)
        }
    }
    
    private func parseLocations(json:JSON) -> [Int:String] {
        var locations:[Int:String] = [:]
        if let jsonArray = json["locations"].array {
            for json in jsonArray {
                let id = json["id"].intValue
                let name = json["name"].stringValue
                locations[id] = name
            }
        }
        return locations
    }
    
    func makeBooking(for booking: GSRBooking, _ callback: @escaping (_ success: Bool, _ failureMessage: String?) -> Void) {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
        let start = dateFormatter.string(from: booking.start)
        let end = dateFormatter.string(from: booking.end)
        
        let basicParams = [
            "lid" : String(booking.location.lid),
            "room" : String(booking.roomId),
            "start" : start,
            "end" : end,
        ]
        let extraParams: [String: String]
        if booking.location.service == "wharton" {
            let sessionID: String = booking.sessionId
            extraParams = [
                "sessionid": sessionID
            ]
        } else {
            let user: GSRUser = booking.user
            extraParams = [
                "firstname" : user.firstName,
                "lastname" : user.lastName,
                "email" : user.email,
                "phone" : user.phone,
                "groupname" : booking.groupName,
                "size" : "2-3"
            ]
        }
        
        let params = basicParams.merging(extraParams, uniquingKeysWith: { (first, _) in first })
        
        guard let url = URL(string: bookingUrl) else { return }
        let request = NSMutableURLRequest(url: url)
        request.httpMethod = "POST"
        let deviceID = getDeviceID()
        request.setValue(deviceID, forHTTPHeaderField: "X-Device-ID")
        request.httpBody = params.stringFromHttpParameters().data(using: String.Encoding.utf8)
        self.bookingRequestOutstanding = true
        let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) in
            var success = false
            var errorMessage = "Unable to connect to the internet. Please reconnect and try again."
            if let response = response as? HTTPURLResponse {
                if response.statusCode == 200 {
                    if let data = data, let _ = NSString(data: data, encoding: String.Encoding.utf8.rawValue) {
                        let json = JSON(data)
                        success = json["results"].boolValue
                        errorMessage = json["error"].stringValue
                    }
                    if errorMessage.contains("\n") {
                        errorMessage = errorMessage.replacingOccurrences(of: "\n", with: " ")
                    }
                } else {
                    // Session ID is invalid, so clear it
                    GSRUser.clearSessionID()
                }
            }
            callback(success, errorMessage)
            self.bookingRequestOutstanding = false
        })
        task.resume()
    }
}

// MARK: - Get Reservatoins
extension GSRNetworkManager {
    func getReservations(sessionID: String?, email: String?, _ callback: @escaping (_ reservations: [GSRReservation]?) -> Void) {
        let url: String
        if let sessionID = sessionID, let email = email {
            url = "\(reservationURL)?sessionid=\(sessionID)&email=\(email)"
        } else if let sessionID = sessionID {
            url = "\(reservationURL)?sessionid=\(sessionID)"
        } else if let email = email {
            url = "\(reservationURL)?email=\(email)"
        } else {
            url = reservationURL
        }
        getRequest(url: url) { (dict, error, status) in
            var reservations: [GSRReservation]? = nil
            if let dict = dict {
                let json = JSON(dict)
                reservations = try? self.parseReservation(json: json)
            }<commit_msg>add auth to booking api<commit_after>//
//  NetworkManager.swift
//  GSR
//
//  Created by <NAME> on 01/02/2018.
//  Copyright © 2016 <NAME>. All rights reserved.
//

import Foundation
import SwiftyJSON

class GSRNetworkManager: NSObject, Requestable {
    
    static let instance = GSRNetworkManager()
    
    let availUrl = "https://api.pennlabs.org/studyspaces/availability"
    let locationsUrl = "https://api.pennlabs.org/studyspaces/locations"
    let bookingUrl = "https://api.pennlabs.org/studyspaces/book"
    let reservationURL = "https://api.pennlabs.org/studyspaces/reservations"
    let cancelURL = "https://api.pennlabs.org/studyspaces/cancel"
    
    var locations:[Int:String] = [:]
    var bookingRequestOutstanding = false
    
    
    func getLocations (callback: @escaping (([Int:String]?) -> Void)) {
        let url = locationsUrl
        getRequest(url: url) { (dict, error, statusCode) in
            if let dict = dict {
                let json = JSON(dict)
                self.locations = self.parseLocations(json: json)
                callback(self.locations)
            } else {
                callback(nil)
            }
        }
    }
    
    func getAvailability(for gsrId: Int, date: GSRDate, callback: @escaping ((_ rooms: [GSRRoom]?) -> Void)) {
        self.getAvailability(for: gsrId, dateStr: date.string) { (rooms) in
            callback(rooms)
        }
    }

    func getAvailability(for gsrId: Int, dateStr: String, callback: @escaping ((_ rooms: [GSRRoom]?) -> Void)) {
        var url = "\(availUrl)/\(gsrId)?date=\(dateStr)"
        if let sessionID = GSRUser.getSessionID() {
            url = "\(url)&sessionid=\(sessionID)"
        }
        getRequest(url: url) { (dict, error, statusCode) in
            var rooms: [GSRRoom]!
            if let dict = dict {
                let json = JSON(dict)
                rooms = Array<GSRRoom>(json: json)
            }
            
            if statusCode == 400 && gsrId == 1 {
                // If Session ID invalid, clear it and try again without one
                GSRUser.clearSessionID()
                self.getAvailability(for: gsrId, dateStr: dateStr, callback: callback)
                return
            }
            callback(rooms)
        }
    }
    
    private func parseLocations(json:JSON) -> [Int:String] {
        var locations:[Int:String] = [:]
        if let jsonArray = json["locations"].array {
            for json in jsonArray {
                let id = json["id"].intValue
                let name = json["name"].stringValue
                locations[id] = name
            }
        }
        return locations
    }
    
    func makeBooking(for booking: GSRBooking, _ callback: @escaping (_ success: Bool, _ failureMessage: String?) -> Void) {
        OAuth2NetworkManager.instance.getAccessToken { (token) in
            let url = URL(string: self.bookingUrl)!
            var request = token != nil ? URLRequest(url: url, accessToken: token!) : URLRequest(url: url)
            request.httpMethod = "POST"
            
            let deviceID = getDeviceID()
            request.setValue(deviceID, forHTTPHeaderField: "X-Device-ID")
            
            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
            let start = dateFormatter.string(from: booking.start)
            let end = dateFormatter.string(from: booking.end)
            
            let basicParams = [
                "lid" : String(booking.location.lid),
                "room" : String(booking.roomId),
                "start" : start,
                "end" : end,
            ]
            let extraParams: [String: String]
            if booking.location.service == "wharton" {
                let sessionID: String = booking.sessionId
                extraParams = [
                    "sessionid": sessionID
                ]
            } else {
                let user: GSRUser = booking.user
                extraParams = [
                    "firstname" : user.firstName,
                    "lastname" : user.lastName,
                    "email" : user.email,
                    "phone" : user.phone,
                    "groupname" : booking.groupName,
                    "size" : "2-3"
                ]
            }
            
            let params = basicParams.merging(extraParams, uniquingKeysWith: { (first, _) in first })
            request.httpBody = params.stringFromHttpParameters().data(using: String.Encoding.utf8)
            
            self.bookingRequestOutstanding = true
            let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) in
                var success = false
                var errorMessage = "Unable to connect to the internet. Please reconnect and try again."
                if let response = response as? HTTPURLResponse {
                    if response.statusCode == 200 {
                        if let data = data, let _ = NSString(data: data, encoding: String.Encoding.utf8.rawValue) {
                            let json = JSON(data)
                            success = json["results"].boolValue
                            errorMessage = json["error"].stringValue
                        }
                        if errorMessage.contains("\n") {
                            errorMessage = errorMessage.replacingOccurrences(of: "\n", with: " ")
                        }
                    } else {
                        // Session ID is invalid, so clear it
                        GSRUser.clearSessionID()
                    }
                }
                callback(success, errorMessage)
                self.bookingRequestOutstanding = false
            })
            task.resume()
        }
    }
}

// MARK: - Get Reservatoins
extension GSRNetworkManager {
    func getReservations(sessionID: String?, email: String?, _ callback: @escaping (_ reservations: [GSRReservation]?) -> Void) {
        let url: String
        if let sessionID = sessionID, let email = email {
            url = "\(reservationURL)?sessionid=\(sessionID)&email=\(email)"
        } else if let sessionID = sessionID {
            url = "\(reservationURL)?sessionid=\(sessionID)"
        } else if let email = email {
            url = "\(reservationURL)?email=\(email)"
        } else {
            url = reservationURL
        }
        getRequest(url: url) { (dict, error, status) in
            var reservations: [GSRReservation]? = nil
            if let dict = dict {
                let json = JSON(dict)
                reservations = try? self.parseReservation(json: json)
            }
{'fraction_non_alphanumeric': 0.1071593533487298, 'fraction_numerical': 0.0036181678214010776, 'mean_word_length': 1.6791090946586926, 'pattern_counts': {'":': 2, '<': 9, '<?xml version=': 0, '>': 21, 'https://': 10, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6644163', 'n_tokens_mistral': 3640, 'n_tokens_neox': 3449, 'n_words': 840}