// Foundation/NSURLSession/Configuration.swift - NSURLSession & libcurl
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
// -----------------------------------------------------------------------------
///
/// These are libcurl helpers for the URLSession API code.
/// - SeeAlso: https://curl.haxx.se/libcurl/c/
/// - SeeAlso: NSURLSession.swift
///
// -----------------------------------------------------------------------------


internal extension URLSession {
    /// This is an immutable / `struct` version of `URLSessionConfiguration`.
    struct _Configuration {
        /// identifier for the background session configuration
        let identifier: String?
        
        /// default cache policy for requests
        let requestCachePolicy: URLRequest.CachePolicy
        
        /// default timeout for requests.  This will cause a timeout if no data is transmitted for the given timeout value, and is reset whenever data is transmitted.
        let timeoutIntervalForRequest: TimeInterval
        
        /// default timeout for requests.  This will cause a timeout if a resource is not able to be retrieved within a given timeout.
        let timeoutIntervalForResource: TimeInterval
        
        /// type of service for requests.
        let networkServiceType: URLRequest.NetworkServiceType
        
        /// allow request to route over cellular.
        let allowsCellularAccess: Bool
        
        /// allows background tasks to be scheduled at the discretion of the system for optimal performance.
        let discretionary: Bool
        
        /// The proxy dictionary, as described by <CFNetwork/CFHTTPStream.h>
        let connectionProxyDictionary: [AnyHashable : Any]?
        
        /// Allow the use of HTTP pipelining
        let httpShouldUsePipelining: Bool
        
        /// Allow the session to set cookies on requests
        let httpShouldSetCookies: Bool
        
        /// Policy for accepting cookies.  This overrides the policy otherwise specified by the cookie storage.
        let httpCookieAcceptPolicy: HTTPCookie.AcceptPolicy
        
        /// Specifies additional headers which will be set on outgoing requests.
        /// Note that these headers are added to the request only if not already present.
        
        let httpAdditionalHeaders: [String : String]?
        /// The maximum number of simultanous persistent connections per host
        let httpMaximumConnectionsPerHost: Int
        
        /// The cookie storage object to use, or nil to indicate that no cookies should be handled
        let httpCookieStorage: HTTPCookieStorage?
        
        /// The credential storage object, or nil to indicate that no credential storage is to be used
        let urlCredentialStorage: URLCredentialStorage?
        
        /// The URL resource cache, or nil to indicate that no caching is to be performed
        let urlCache: URLCache?
        
        /// Enable extended background idle mode for any tcp sockets created.
        let shouldUseExtendedBackgroundIdleMode: Bool
        
        let protocolClasses: [AnyClass]?
    }
}
internal extension URLSession._Configuration {
    init(URLSessionConfiguration config: URLSessionConfiguration) {
        identifier = config.identifier
        requestCachePolicy = config.requestCachePolicy
        timeoutIntervalForRequest = config.timeoutIntervalForRequest
        timeoutIntervalForResource = config.timeoutIntervalForResource
        networkServiceType = config.networkServiceType
        allowsCellularAccess = config.allowsCellularAccess
        discretionary = config.discretionary
        connectionProxyDictionary = config.connectionProxyDictionary
        httpShouldUsePipelining = config.httpShouldUsePipelining
        httpShouldSetCookies = config.httpShouldSetCookies
        httpCookieAcceptPolicy = config.httpCookieAcceptPolicy
        httpAdditionalHeaders = config.httpAdditionalHeaders.map { convertToStringString(dictionary: $0) }
        httpMaximumConnectionsPerHost = config.httpMaximumConnectionsPerHost
        httpCookieStorage = config.httpCookieStorage
        urlCredentialStorage = config.urlCredentialStorage
        urlCache = config.urlCache
        shouldUseExtendedBackgroundIdleMode = config.shouldUseExtendedBackgroundIdleMode
        protocolClasses = config.protocolClasses
    }
}

// Configure NSURLRequests
internal extension URLSession._Configuration {
    func configure(request: URLRequest) {
        var request = request
        httpAdditionalHeaders?.forEach {
            guard request.value(forHTTPHeaderField: $0.0) == nil else { return }
            request.setValue($0.1, forHTTPHeaderField: $0.0)
        }
    }
    func setCookies(on request: URLRequest) {
        if httpShouldSetCookies {
            //TODO: Ask the cookie storage what cookie to set.
        }
    }
}
// Cache Management
private extension URLSession._Configuration {
    func cachedResponse(forRequest request: URLRequest) -> CachedURLResponse? {
        //TODO: Check the policy & consult the cache.
        // There's more detail on how this should work here:
        // <https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSURLRequest_Class/index.html#//apple_ref/swift/enum/c:@E@URLRequestCachePolicy>
        switch requestCachePolicy {
        default: return nil
        }
    }
}

private func convertToStringString(dictionary: [AnyHashable:Any]) -> [String: String] {
    //TODO: There's some confusion about [NSObject:AnyObject] vs. [String:String] for headers.
    // C.f. <https://github.com/apple/swift-corelibs-foundation/pull/287>
    var r: [String: String] = [:]
    dictionary.forEach {
        let k = getString(from: $0.key)
        let v = getString(from: $0.value)
        r[k] = v
    }
    return r
}

private func getString(from obj: Any) -> String {
    if let string = obj as? String {
        return string
    } else {
        return String(describing: obj as! NSString)
    }
}
