/*
 *  Copyright 2014 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

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

#include "webrtc/base/gunit.h"
#include "webrtc/base/ssladapter.h"

#import "WebRTC/RTCMediaConstraints.h"
#import "WebRTC/RTCPeerConnectionFactory.h"
#import "WebRTC/RTCSessionDescription.h"

#import "ARDAppClient+Internal.h"
#import "ARDJoinResponse+Internal.h"
#import "ARDMessageResponse+Internal.h"
#import "ARDSDPUtils.h"

// These classes mimic XCTest APIs, to make eventual conversion to XCTest
// easier. Conversion will happen once XCTest is supported well on build bots.
@interface ARDTestExpectation : NSObject

@property(nonatomic, readonly) NSString *description;
@property(nonatomic, readonly) BOOL isFulfilled;

- (instancetype)initWithDescription:(NSString *)description;
- (void)fulfill;

@end

@implementation ARDTestExpectation

@synthesize description = _description;
@synthesize isFulfilled = _isFulfilled;

- (instancetype)initWithDescription:(NSString *)description {
  if (self = [super init]) {
    _description = description;
  }
  return self;
}

- (void)fulfill {
  _isFulfilled = YES;
}

@end

@interface ARDTestCase : NSObject

- (ARDTestExpectation *)expectationWithDescription:(NSString *)description;
- (void)waitForExpectationsWithTimeout:(NSTimeInterval)timeout
                               handler:(void (^)(NSError *error))handler;

@end

@implementation ARDTestCase {
  NSMutableArray *_expectations;
}

- (instancetype)init {
  if (self = [super init]) {
   _expectations = [NSMutableArray array];
  }
  return self;
}

- (ARDTestExpectation *)expectationWithDescription:(NSString *)description {
  ARDTestExpectation *expectation =
      [[ARDTestExpectation alloc] initWithDescription:description];
  [_expectations addObject:expectation];
  return expectation;
}

- (void)waitForExpectationsWithTimeout:(NSTimeInterval)timeout
                               handler:(void (^)(NSError *error))handler {
  NSDate *startDate = [NSDate date];
  while (![self areExpectationsFulfilled]) {
    NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:startDate];
    if (duration > timeout) {
      NSAssert(NO, @"Expectation timed out.");
      break;
    }
    [[NSRunLoop currentRunLoop]
        runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
  }
  handler(nil);
}

- (BOOL)areExpectationsFulfilled {
  for (ARDTestExpectation *expectation in _expectations) {
    if (!expectation.isFulfilled) {
      return NO;
    }
  }
  return YES;
}

@end

@interface ARDAppClientTest : ARDTestCase
@end

@implementation ARDAppClientTest

#pragma mark - Mock helpers

- (id)mockRoomServerClientForRoomId:(NSString *)roomId
                           clientId:(NSString *)clientId
                        isInitiator:(BOOL)isInitiator
                           messages:(NSArray *)messages
                     messageHandler:
    (void (^)(ARDSignalingMessage *))messageHandler {
  id mockRoomServerClient =
      [OCMockObject mockForProtocol:@protocol(ARDRoomServerClient)];

  // Successful join response.
  ARDJoinResponse *joinResponse = [[ARDJoinResponse alloc] init];
  joinResponse.result = kARDJoinResultTypeSuccess;
  joinResponse.roomId = roomId;
  joinResponse.clientId = clientId;
  joinResponse.isInitiator = isInitiator;
  joinResponse.messages = messages;

  // Successful message response.
  ARDMessageResponse *messageResponse = [[ARDMessageResponse alloc] init];
  messageResponse.result = kARDMessageResultTypeSuccess;

  // Return join response from above on join.
  [[[mockRoomServerClient stub] andDo:^(NSInvocation *invocation) {
    __unsafe_unretained void (^completionHandler)(ARDJoinResponse *response,
                                                  NSError *error);
    [invocation getArgument:&completionHandler atIndex:3];
    completionHandler(joinResponse, nil);
  }] joinRoomWithRoomId:roomId isLoopback:NO completionHandler:[OCMArg any]];

  // Return message response from above on join.
  [[[mockRoomServerClient stub] andDo:^(NSInvocation *invocation) {
    __unsafe_unretained ARDSignalingMessage *message;
    __unsafe_unretained void (^completionHandler)(ARDMessageResponse *response,
                                                  NSError *error);
    [invocation getArgument:&message atIndex:2];
    [invocation getArgument:&completionHandler atIndex:5];
    messageHandler(message);
    completionHandler(messageResponse, nil);
  }] sendMessage:[OCMArg any]
            forRoomId:roomId
             clientId:clientId
    completionHandler:[OCMArg any]];

  // Do nothing on leave.
  [[[mockRoomServerClient stub] andDo:^(NSInvocation *invocation) {
    __unsafe_unretained void (^completionHandler)(NSError *error);
    [invocation getArgument:&completionHandler atIndex:4];
    if (completionHandler) {
      completionHandler(nil);
    }
  }] leaveRoomWithRoomId:roomId
                clientId:clientId
       completionHandler:[OCMArg any]];

  return mockRoomServerClient;
}

- (id)mockSignalingChannelForRoomId:(NSString *)roomId
                           clientId:(NSString *)clientId
                     messageHandler:
    (void (^)(ARDSignalingMessage *message))messageHandler {
  id mockSignalingChannel =
      [OCMockObject niceMockForProtocol:@protocol(ARDSignalingChannel)];
  [[mockSignalingChannel stub] registerForRoomId:roomId clientId:clientId];
  [[[mockSignalingChannel stub] andDo:^(NSInvocation *invocation) {
    __unsafe_unretained ARDSignalingMessage *message;
    [invocation getArgument:&message atIndex:2];
    messageHandler(message);
  }] sendMessage:[OCMArg any]];
  return mockSignalingChannel;
}

- (id)mockTURNClient {
  id mockTURNClient =
      [OCMockObject mockForProtocol:@protocol(ARDTURNClient)];
  [[[mockTURNClient stub] andDo:^(NSInvocation *invocation) {
    // Don't return anything in TURN response.
    __unsafe_unretained void (^completionHandler)(NSArray *turnServers,
                                                  NSError *error);
    [invocation getArgument:&completionHandler atIndex:2];
    completionHandler([NSArray array], nil);
  }] requestServersWithCompletionHandler:[OCMArg any]];
  return mockTURNClient;
}

- (ARDAppClient *)createAppClientForRoomId:(NSString *)roomId
                                  clientId:(NSString *)clientId
                               isInitiator:(BOOL)isInitiator
                                  messages:(NSArray *)messages
                            messageHandler:
    (void (^)(ARDSignalingMessage *message))messageHandler
                          connectedHandler:(void (^)(void))connectedHandler {
  id turnClient = [self mockTURNClient];
  id signalingChannel = [self mockSignalingChannelForRoomId:roomId
                                                   clientId:clientId
                                             messageHandler:messageHandler];
  id roomServerClient =
      [self mockRoomServerClientForRoomId:roomId
                                 clientId:clientId
                              isInitiator:isInitiator
                                 messages:messages
                           messageHandler:messageHandler];
  id delegate =
      [OCMockObject niceMockForProtocol:@protocol(ARDAppClientDelegate)];
  [[[delegate stub] andDo:^(NSInvocation *invocation) {
    connectedHandler();
  }] appClient:[OCMArg any]
      didChangeConnectionState:RTCIceConnectionStateConnected];

  return [[ARDAppClient alloc] initWithRoomServerClient:roomServerClient
                                       signalingChannel:signalingChannel
                                             turnClient:turnClient
                                               delegate:delegate];
}

// Tests that an ICE connection is established between two ARDAppClient objects
// where one is set up as a caller and the other the answerer. Network
// components are mocked out and messages are relayed directly from object to
// object. It's expected that both clients reach the
// RTCIceConnectionStateConnected state within a reasonable amount of time.
- (void)testSession {
  // Need block arguments here because we're setting up a callbacks before we
  // create the clients.
  ARDAppClient *caller = nil;
  ARDAppClient *answerer = nil;
  __block __weak ARDAppClient *weakCaller = nil;
  __block __weak ARDAppClient *weakAnswerer = nil;
  NSString *roomId = @"testRoom";
  NSString *callerId = @"testCallerId";
  NSString *answererId = @"testAnswererId";

  ARDTestExpectation *callerConnectionExpectation =
      [self expectationWithDescription:@"Caller PC connected."];
  ARDTestExpectation *answererConnectionExpectation =
      [self expectationWithDescription:@"Answerer PC connected."];

  caller = [self createAppClientForRoomId:roomId
                                 clientId:callerId
                              isInitiator:YES
                                 messages:[NSArray array]
                           messageHandler:^(ARDSignalingMessage *message) {
    ARDAppClient *strongAnswerer = weakAnswerer;
    [strongAnswerer channel:strongAnswerer.channel didReceiveMessage:message];
  } connectedHandler:^{
    [callerConnectionExpectation fulfill];
  }];
  // TODO(tkchin): Figure out why DTLS-SRTP constraint causes thread assertion
  // crash in Debug.
  caller.defaultPeerConnectionConstraints =
      [[RTCMediaConstraints alloc] initWithMandatoryConstraints:nil
                                            optionalConstraints:nil];
  weakCaller = caller;

  answerer = [self createAppClientForRoomId:roomId
                                   clientId:answererId
                                isInitiator:NO
                                   messages:[NSArray array]
                             messageHandler:^(ARDSignalingMessage *message) {
    ARDAppClient *strongCaller = weakCaller;
    [strongCaller channel:strongCaller.channel didReceiveMessage:message];
  } connectedHandler:^{
    [answererConnectionExpectation fulfill];
  }];
  // TODO(tkchin): Figure out why DTLS-SRTP constraint causes thread assertion
  // crash in Debug.
  answerer.defaultPeerConnectionConstraints =
      [[RTCMediaConstraints alloc] initWithMandatoryConstraints:nil
                                            optionalConstraints:nil];
  weakAnswerer = answerer;

  // Kick off connection.
  [caller connectToRoomWithId:roomId
                   isLoopback:NO
                  isAudioOnly:NO
            shouldMakeAecDump:NO
        shouldUseLevelControl:NO];
  [answerer connectToRoomWithId:roomId
                     isLoopback:NO
                    isAudioOnly:NO
              shouldMakeAecDump:NO
          shouldUseLevelControl:NO];
  [self waitForExpectationsWithTimeout:20 handler:^(NSError *error) {
    if (error) {
      NSLog(@"Expectations error: %@", error);
    }
  }];
}

@end

@interface ARDSDPUtilsTest : ARDTestCase
- (void)testPreferVideoCodec;
@end

@implementation ARDSDPUtilsTest

- (void)testPreferVideoCodec {
  NSString *sdp = @("m=video 9 RTP/SAVPF 100 116 117 96 120\n"
                    "a=rtpmap:120 H264/90000\n");
  NSString *expectedSdp = @("m=video 9 RTP/SAVPF 120 100 116 117 96\n"
                            "a=rtpmap:120 H264/90000\n");
  RTCSessionDescription* desc =
      [[RTCSessionDescription alloc] initWithType:RTCSdpTypeOffer sdp:sdp];
  RTCSessionDescription *h264Desc =
      [ARDSDPUtils descriptionForDescription:desc
                         preferredVideoCodec:@"H264"];
  EXPECT_TRUE([h264Desc.description isEqualToString:expectedSdp]);
}

@end

class SignalingTest : public ::testing::Test {
 protected:
  static void SetUpTestCase() {
    rtc::InitializeSSL();
  }
  static void TearDownTestCase() {
    rtc::CleanupSSL();
  }
};

TEST_F(SignalingTest, SessionTest) {
  @autoreleasepool {
    ARDAppClientTest *test = [[ARDAppClientTest alloc] init];
    [test testSession];
  }
}

TEST_F(SignalingTest, SDPTest) {
  @autoreleasepool {
    ARDSDPUtilsTest *test = [[ARDSDPUtilsTest alloc] init];
    [test testPreferVideoCodec];
  }
}


