//
//  CRSessionControllerDelegateTests.m
//  Courier
//
//  Created by absmith on 1/13/15.
//  Copyright (c) 2014 Andrew B. Smith ( http://github.com/drewsmits ). All rights reserved.
//
// 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 <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import "CRTestCase.h"

#import "CRSessionController.h"
#import "CRAsyncTestHelpers.h"

#import <OHHTTPStubs/OHHTTPStubs.h>
#import <OCMock/OCMock.h>

static NSString * const kTestRedirectURL = @"http://www.redirect.com";

@interface CRSessionController (Private)

@property (nonatomic, readonly) NSOperationQueue *serialQueue;

- (id <NSURLSessionTaskDelegate>)NSURLSessionTaskDelegateForTask:(NSURLSessionTask *)task;

- (void)addTask:(NSURLSessionTask *)task
      withToken:(NSString *)token
        toGroup:(NSString *)group;

- (void)removeTaskWithToken:(NSString *)token;

@end

@interface CRSessionControllerDelegateTests : CRTestCase
@property (nonatomic, strong) CRSessionController *sessionController;
@end

@implementation CRSessionControllerDelegateTests

- (void)setUp
{
    [super setUp];
    
    _sessionController = [CRSessionController sessionControllerWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration]];
    
    [OHHTTPStubs removeAllStubs];
    
    [[NSURLSessionConfiguration ephemeralSessionConfiguration].URLCache removeAllCachedResponses];
}

- (void)tearDown
{
    [OHHTTPStubs removeAllStubs];
    [super tearDown];
}

- (void)testAddDelegate
{
    NSURLSessionDataTask *task = OCMClassMock([NSURLSessionDataTask class]);
    id mockDelegate = OCMProtocolMock(@protocol(NSURLSessionTaskDelegate));
    [_sessionController addNSURLSessionTaskDelegate:mockDelegate
                                            forTask:task];

    id shouldBeDelegate = [_sessionController NSURLSessionTaskDelegateForTask:task];
    
    XCTAssertEqualObjects(shouldBeDelegate,
                          mockDelegate,
                          @"Session controller should return the correct delegate");
}

- (void)testRemoveDelegate
{
    NSURLSessionDataTask *task = OCMClassMock([NSURLSessionDataTask class]);
    id mockDelegate = OCMProtocolMock(@protocol(NSURLSessionTaskDelegate));
    [_sessionController addNSURLSessionTaskDelegate:mockDelegate
                                            forTask:task];

    [_sessionController removeNSURLSessionTaskDelegate:mockDelegate];
    id delegate = [_sessionController NSURLSessionTaskDelegateForTask:task];
    
    XCTAssertNil(delegate);
}

- (void)testRemoveTaskWithDelegate
{
    // Add task first
    NSURLSessionTask *task = [NSURLSessionTask new];
    [_sessionController addTask:task
                      withToken:@"blah"
                        toGroup:@"blah"];
    
    id mockDelegate = OCMProtocolMock(@protocol(NSURLSessionTaskDelegate));
    [_sessionController addNSURLSessionTaskDelegate:mockDelegate
                                            forTask:task];

    [_sessionController removeTaskWithToken:@"blah"];
    [_sessionController.serialQueue waitUntilAllOperationsAreFinished];
    id delegate = [_sessionController NSURLSessionTaskDelegateForTask:task];
    
    XCTAssertNil(delegate);
}

- (void)testRedirectResponseDelegate
{
    //
    // Stub redirect responses
    //
    [OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) {
        return [request.URL.absoluteString isEqualToString:kTestRedirectURL];
    } withStubResponse:^OHHTTPStubsResponse *(NSURLRequest *request) {
        return [OHHTTPStubsResponse responseWithData:[@"dummyData" dataUsingEncoding:NSUTF8StringEncoding]
                                          statusCode:301
                                             headers:@{@"Location" : @"http://www.nest.com"}];
    }];
    
    XCTestExpectation *expectation = [self expectationWithDescription:@"taskFinished"];
    
    NSURLRequest *redirectRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:kTestRedirectURL]];
    NSURLSessionDataTask *task = [_sessionController dataTaskForRequest:redirectRequest
                                                      completionHandler:^(NSData *data,
                                                                          NSURLResponse *response,
                                                                          BOOL cachedResponse,
                                                                          NSError *error) {
                                                          [expectation fulfill];
                                                      }];

    //
    // Add delegate and expect the redirect is invoked
    //
    id mockDelegate = OCMProtocolMock(@protocol(NSURLSessionTaskDelegate));

    // forward redirect to self. This lets the redirect complete.
    OCMStub([mockDelegate URLSession:OCMOCK_ANY
                                task:OCMOCK_ANY
          willPerformHTTPRedirection:OCMOCK_ANY
                          newRequest:OCMOCK_ANY
                   completionHandler:OCMOCK_ANY]).andCall(self,
                                                          @selector(URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:));

    // forward auth challenge to self. This lets the redirect complete.
    OCMStub([mockDelegate URLSession:OCMOCK_ANY
                                task:OCMOCK_ANY
                 didReceiveChallenge:OCMOCK_ANY
                   completionHandler:OCMOCK_ANY]).andCall(self,
                                                          @selector(URLSession:task:didReceiveChallenge:completionHandler:));

    [_sessionController addNSURLSessionTaskDelegate:mockDelegate
                                            forTask:task];
    [task resume];

    [self waitForExpectationsWithTimeout:1.0
                                 handler:nil];

    //
    // Verify that the delegate gets called.
    //
    OCMVerify([mockDelegate URLSession:OCMOCK_ANY
                                  task:OCMOCK_ANY
            willPerformHTTPRedirection:OCMOCK_ANY
                            newRequest:OCMOCK_ANY
                     completionHandler:OCMOCK_ANY]);
}

- (void)URLSession:(NSURLSession *)session
              task:(NSURLSessionTask *)task
willPerformHTTPRedirection:(NSHTTPURLResponse *)response
        newRequest:(NSURLRequest *)request
 completionHandler:(void (^)(NSURLRequest *))completionHandler
{
    if (completionHandler) completionHandler(request);
}

- (void)URLSession:(NSURLSession *)session
              task:(NSURLSessionTask *)task
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler
{
    if (completionHandler) {
        completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
    }
    
}

@end
