<commit_before>//
//  Network.swift
//  TCAT
//
//  Created by <NAME> on 4/6/17.
//  Copyright © 2017 cuappdev. All rights reserved.
//

import Foundation
import SwiftyJSON
import TRON
import CoreLocation
import GooglePlaces
import Alamofire

enum NetworkType: String {
    case local, debug, release
}

class Network {

    // MARK: Global Network Variables
    
    /// Testing local servers for Network
    // Change `networkType` to `.local` to work locally.
    // Change `localIPAddress` to be the proper address
    
    static let networkType: NetworkType = .release
    static let apiVersion = "v1"

    /// Used for local backend testing
    static let localIPAddress = "10.132.0.68"
    static let localSource = "http://\(localIPAddress):3000/api/\(apiVersion)/"

    /// Test server used for development
    static let debugIPAddress = "172.16.31.10"
    static let debugSource = "http://\(debugIPAddress)/api/\(apiVersion)/"
    
    /// Deployed server instance used for release
    static let releaseIPAddress = "transit-backend.cornellappdev.com"
    static let releaseSource = "http://\(releaseIPAddress)/api/\(apiVersion)/"
    
    /// Network IP address being used for specified networkType
    static var ipAddress: String {
        switch networkType {
        case .local: return localIPAddress
        case .debug: return debugIPAddress
        case .release: return releaseIPAddress
        }
    }

    /// Network source currently being used
    static var address: String {
        switch networkType {
        case .local: return localSource
        case .debug: return debugSource
        case .release: return releaseSource
        }
    }

    static let tron = TRON(baseURL: Network.address)

    class func getAllStops() -> APIRequest<AllBusStops, Error> {
        let request: APIRequest<AllBusStops, Error> = tron.swiftyJSON.request("allStops")
        request.method = .get
        return request
    }

    class func getCoordinates(start: CoordinateAcceptor, end: CoordinateAcceptor,
                              callback: @escaping (_ startCoord: CLLocationCoordinate2D?, _ endCoord: CLLocationCoordinate2D?, _ error: CoordinateVisitorError?) -> Void ) {
        
        let visitor = CoordinateVisitor()
        
        start.accept(visitor: visitor) { (startCoord, error) in
            
            guard let startCoord = startCoord else {
                callback(nil, nil, error)
                return
            }
            
            end.accept(visitor: visitor) { (endCoord, error) in
                
                guard let endCoord = endCoord else {
                    callback(nil, nil, error)
                    return
                }
                
                callback(startCoord, endCoord, nil)
                
            }
            
        }

    }

    class func getRoutes(startCoord: CLLocationCoordinate2D, endCoord: CLLocationCoordinate2D, endPlaceName: String, time: Date, type: SearchType,
                         callback: @escaping (_ request: APIRequest<JSON, Error>) -> Void) {
        
        let request: APIRequest<JSON, Error> = tron.swiftyJSON.request("route")
        request.method = .get
        request.parameters = [
            "arriveBy"          :   type == .arriveBy,
            "end"               :   "\(endCoord.latitude),\(endCoord.longitude)",
            "start"             :   "\(startCoord.latitude),\(startCoord.longitude)",
            "time"              :   time.timeIntervalSince1970,
            "destinationName"   :   endPlaceName
        ]
        
        // Add unique identifier to request
        if let uid = userDefaults.string(forKey: Constants.UserDefaults.uid) {
            request.parameters["uid"] = uid
        }
        
        callback(request)
    }
    
    class func getRequestUrl(startCoord: CLLocationCoordinate2D, endCoord: CLLocationCoordinate2D, destinationName: String, time: Date, type: SearchType) -> String {
        let path = "route"
        let arriveBy = (type == .arriveBy)
        let end = "\(endCoord.latitude),\(endCoord.longitude)"
        let start =  "\(startCoord.latitude),\(startCoord.longitude)"
        let time = time.timeIntervalSince1970
        
        return  "\(address)\(path)?arriveBy=\(arriveBy)&end=\(end)&start=\(start)&time=\(time)&destinationName=\(destinationName)"
    }


    class func getGooglePlacesAutocompleteResults(searchText: String) -> APIRequest<JSON, Error> {
        let request: APIRequest<JSON, Error> = tron.swiftyJSON.request("places")
        request.method = .post
        request.parameterEncoding = JSONEncoding.default
        request.parameters = ["query" : searchText]
        
        // Add unique identifier to request
        if let uid = userDefaults.string(forKey: Constants.UserDefaults.uid) {
            request.parameters["uid"] = uid
        }
        
        return request
    }
    
    class func routeSelected(rowIndex: Int) -> APIRequest<JSON, Error> {
        let request: APIRequest<JSON, Error> = tron.swiftyJSON.request("routeSelected")
        request.method = .post
        request.parameterEncoding = JSONEncoding.default
        request.parameters = ["rowIndex" : rowIndex]
        
        // Add unique identifier to request
        if let uid = userDefaults.string(forKey: Constants.UserDefaults.uid) {
            request.parameters["uid"] = uid
        }
        
        return request
    }

    class func getBusLocations(_ directions: [Direction]) -> APIRequest<BusLocationResult, Error> {

        let request: APIRequest<BusLocationResult, Error> = tron.swiftyJSON.request("tracking")
        request.method = .post
        let departDirections = directions.filter { $0.type == .depart && $0.tripIdentifiers != nil }
        let dictionary = departDirections.map { (direction) -> [String : Any] in

            // The id of the location, or bus stop, the bus needs to get to
            let stopID = direction.startLocation.id

            return [
                "stopID"                :   stopID,
                "routeID"               :   String(direction.routeNumber),
                "tripIdentifiers"       :   direction.tripIdentifiers!
            ]

        }<commit_msg>Reduced warnings<commit_after>//
//  Network.swift
//  TCAT
//
//  Created by <NAME> on 4/6/17.
//  Copyright © 2017 cuappdev. All rights reserved.
//

import Foundation
import SwiftyJSON
import TRON
import CoreLocation
import GooglePlaces
import Alamofire

enum NetworkType: String {
    case local, debug, release
}

class Network {

    // MARK: Global Network Variables
    
    /// Testing local servers for Network
    // Change `networkType` to `.local` to work locally.
    // Change `localIPAddress` to be the proper address
    
    static let networkType: NetworkType = .release
    static let apiVersion = "v1"

    /// Used for local backend testing
    static let localIPAddress = "10.132.0.68"
    static let localSource = "http://\(localIPAddress):3000/api/\(apiVersion)/"

    /// Test server used for development
    static let debugIPAddress = "172.16.31.10"
    static let debugSource = "http://\(debugIPAddress)/api/\(apiVersion)/"
    
    /// Deployed server instance used for release
    static let releaseIPAddress = "transit-backend.cornellappdev.com"
    static let releaseSource = "http://\(releaseIPAddress)/api/\(apiVersion)/"
    
    /// Network IP address being used for specified networkType
    static var ipAddress: String {
        switch networkType {
        case .local: return localIPAddress
        case .debug: return debugIPAddress
        case .release: return releaseIPAddress
        }
    }

    /// Network source currently being used
    static var address: String {
        switch networkType {
        case .local: return localSource
        case .debug: return debugSource
        case .release: return releaseSource
        }
    }

    static let tron = TRON(baseURL: Network.address)

    class func getAllStops() -> APIRequest<AllBusStops, Error> {
        let request: APIRequest<AllBusStops, Error> = tron.swiftyJSON.request("allStops")
        request.method = .get
        return request
    }

    class func getCoordinates(start: CoordinateAcceptor, end: CoordinateAcceptor,
                              callback: @escaping (_ startCoord: CLLocationCoordinate2D?, _ endCoord: CLLocationCoordinate2D?, _ error: CoordinateVisitorError?) -> Void ) {
        
        let visitor = CoordinateVisitor()
        
        start.accept(visitor: visitor) { (startCoord, error) in
            
            guard let startCoord = startCoord else {
                callback(nil, nil, error)
                return
            }
            
            end.accept(visitor: visitor) { (endCoord, error) in
                
                guard let endCoord = endCoord else {
                    callback(nil, nil, error)
                    return
                }
                
                callback(startCoord, endCoord, nil)
                
            }
            
        }

    }

    class func getRoutes(startCoord: CLLocationCoordinate2D, endCoord: CLLocationCoordinate2D, endPlaceName: String, time: Date, type: SearchType,
                         callback: @escaping (_ request: APIRequest<JSON, Error>) -> Void) {
        
        let request: APIRequest<JSON, Error> = tron.swiftyJSON.request("route")
        request.method = .get
        request.parameters = [
            "arriveBy"          :   type == .arriveBy,
            "end"               :   "\(endCoord.latitude),\(endCoord.longitude)",
            "start"             :   "\(startCoord.latitude),\(startCoord.longitude)",
            "time"              :   time.timeIntervalSince1970,
            "destinationName"   :   endPlaceName
        ]
        
        // Add unique identifier to request
        if let uid = userDefaults.string(forKey: Constants.UserDefaults.uid) {
            request.parameters["uid"] = uid
        }
        
        callback(request)
    }
    
    class func getRequestUrl(startCoord: CLLocationCoordinate2D, endCoord: CLLocationCoordinate2D, destinationName: String, time: Date, type: SearchType) -> String {
        let path = "route"
        let arriveBy = (type == .arriveBy)
        let end = "\(endCoord.latitude),\(endCoord.longitude)"
        let start =  "\(startCoord.latitude),\(startCoord.longitude)"
        let time = time.timeIntervalSince1970
        
        return  "\(address)\(path)?arriveBy=\(arriveBy)&end=\(end)&start=\(start)&time=\(time)&destinationName=\(destinationName)"
    }


    class func getGooglePlacesAutocompleteResults(searchText: String) -> APIRequest<JSON, Error> {
        let request: APIRequest<JSON, Error> = tron.swiftyJSON.request("places")
        request.method = .post
        request.parameterEncoding = JSONEncoding.default
        request.parameters = ["query" : searchText]
        
        // Add unique identifier to request
        if let uid = userDefaults.string(forKey: Constants.UserDefaults.uid) {
            request.parameters["uid"] = uid
        }
        
        return request
    }
    
    @discardableResult
    class func routeSelected(rowIndex: Int) -> APIRequest<JSON, Error> {
        let request: APIRequest<JSON, Error> = tron.swiftyJSON.request("routeSelected")
        request.method = .post
        request.parameterEncoding = JSONEncoding.default
        request.parameters = ["rowIndex" : rowIndex]
        
        // Add unique identifier to request
        if let uid = userDefaults.string(forKey: Constants.UserDefaults.uid) {
            request.parameters["uid"] = uid
        }
        
        return request
    }

    class func getBusLocations(_ directions: [Direction]) -> APIRequest<BusLocationResult, Error> {

        let request: APIRequest<BusLocationResult, Error> = tron.swiftyJSON.request("tracking")
        request.method = .post
        let departDirections = directions.filter { $0.type == .depart && $0.tripIdentifiers != nil }
        let dictionary = departDirections.map { (direction) -> [String : Any] in

            // The id of the location, or bus stop, the bus needs to get to
            let stopID = direction.startLocation.id

            return [
                "stopID"                :   stopID,
                "routeID"               :   String(direction.routeNumber),
                "tripIdentifiers"       :   direction.tripIdentifiers!
            ]

        }
{'fraction_non_alphanumeric': 0.09817570811329812, 'fraction_numerical': 0.007361177788446151, 'mean_word_length': 2.06423142927188, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 4, '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': '1525808', 'n_tokens_mistral': 3426, 'n_tokens_neox': 3280, 'n_words': 846}