// URLProtocolTests.swift
//
// Copyright (c) 2014–2016 Alamofire Software Foundation (http://alamofire.org/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

import Alamofire
import Foundation
import XCTest

class ProxyURLProtocol: NSURLProtocol {

    // MARK: Properties

    struct PropertyKeys {
        static let HandledByForwarderURLProtocol = "HandledByProxyURLProtocol"
    }

    lazy var session: NSURLSession = {
        let configuration: NSURLSessionConfiguration = {
            let configuration = NSURLSessionConfiguration.ephemeralSessionConfiguration()
            configuration.HTTPAdditionalHeaders = Alamofire.Manager.defaultHTTPHeaders

            return configuration
        }()

        let session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil)

        return session
    }()

    var activeTask: NSURLSessionTask?

    // MARK: Class Request Methods

    override class func canInitWithRequest(request: NSURLRequest) -> Bool {
        if NSURLProtocol.propertyForKey(PropertyKeys.HandledByForwarderURLProtocol, inRequest: request) != nil {
            return false
        }

        return true
    }

    override class func canonicalRequestForRequest(request: NSURLRequest) -> NSURLRequest {
        return request
    }

    override class func requestIsCacheEquivalent(a: NSURLRequest, toRequest b: NSURLRequest) -> Bool {
        return false
    }

    // MARK: Loading Methods

    override func startLoading() {
        let mutableRequest = request.URLRequest
        NSURLProtocol.setProperty(true, forKey: PropertyKeys.HandledByForwarderURLProtocol, inRequest: mutableRequest)

        activeTask = session.dataTaskWithRequest(mutableRequest)
        activeTask?.resume()
    }

    override func stopLoading() {
        activeTask?.cancel()
    }
}

// MARK: -

extension ProxyURLProtocol: NSURLSessionDelegate {

    // MARK: NSURLSessionDelegate

    func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {
        client?.URLProtocol(self, didLoadData: data)
    }

    func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
        if let response = task.response {
            client?.URLProtocol(self, didReceiveResponse: response, cacheStoragePolicy: .NotAllowed)
        }

        client?.URLProtocolDidFinishLoading(self)
    }
}

// MARK: -

class URLProtocolTestCase: BaseTestCase {

    // MARK: Setup and Teardown Methods

    override func setUp() {
        super.setUp()

        let configuration = Alamofire.Manager.sharedInstance.session.configuration

        configuration.protocolClasses = [ProxyURLProtocol.self]
        configuration.HTTPAdditionalHeaders = ["Session-Configuration-Header": "foo"]
    }

    override func tearDown() {
        super.tearDown()

        Alamofire.Manager.sharedInstance.session.configuration.protocolClasses = []
    }

    // MARK: Tests

    func testThatURLProtocolReceivesRequestHeadersAndNotSessionConfigurationHeaders() {
        // Given
        let URLString = "https://httpbin.org/response-headers"
        let URL = NSURL(string: URLString)!
        let parameters = ["request-header": "foobar"]

        let mutableURLRequest = NSMutableURLRequest(URL: URL)
        mutableURLRequest.HTTPMethod = Method.GET.rawValue

        let URLRequest = ParameterEncoding.URL.encode(mutableURLRequest, parameters: parameters).0

        let expectation = expectationWithDescription("GET request should succeed")

        var request: NSURLRequest?
        var response: NSHTTPURLResponse?
        var data: NSData?
        var error: NSError?

        // When
        Alamofire.request(URLRequest)
            .response { responseRequest, responseResponse, responseData, responseError in
                request = responseRequest
                response = responseResponse
                data = responseData
                error = responseError

                expectation.fulfill()
            }

        waitForExpectationsWithTimeout(timeout, handler: nil)

        // Then
        XCTAssertNotNil(request, "request should not be nil")
        XCTAssertNotNil(response, "response should not be nil")
        XCTAssertNotNil(data, "data should not be nil")
        XCTAssertNil(error, "error should be nil")

        if let headers = response?.allHeaderFields as? [String: String] {
            XCTAssertEqual(headers["request-header"] ?? "", "foobar", "urlrequest-header should be foobar")
            XCTAssertNil(headers["Session-Configuration-Header"], "Session-Configuration-Header should be nil")
        } else {
            XCTFail("headers should not be nil")
        }
    }
}
