/*
 *  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 "ARDAppEngineClient.h"

#import "WebRTC/RTCLogging.h"

#import "ARDJoinResponse.h"
#import "ARDMessageResponse.h"
#import "ARDSignalingMessage.h"
#import "ARDUtilities.h"

// TODO(tkchin): move these to a configuration object.
static NSString * const kARDRoomServerHostUrl =
    @"https://appr.tc";
static NSString * const kARDRoomServerJoinFormat =
    @"https://appr.tc/join/%@";
static NSString * const kARDRoomServerJoinFormatLoopback =
    @"https://appr.tc/join/%@?debug=loopback";
static NSString * const kARDRoomServerMessageFormat =
    @"https://appr.tc/message/%@/%@";
static NSString * const kARDRoomServerLeaveFormat =
    @"https://appr.tc/leave/%@/%@";

static NSString * const kARDAppEngineClientErrorDomain = @"ARDAppEngineClient";
static NSInteger const kARDAppEngineClientErrorBadResponse = -1;

@implementation ARDAppEngineClient

#pragma mark - ARDRoomServerClient

- (void)joinRoomWithRoomId:(NSString *)roomId
                isLoopback:(BOOL)isLoopback
         completionHandler:(void (^)(ARDJoinResponse *response,
                                     NSError *error))completionHandler {
  NSParameterAssert(roomId.length);

  NSString *urlString = nil;
  if (isLoopback) {
    urlString =
        [NSString stringWithFormat:kARDRoomServerJoinFormatLoopback, roomId];
  } else {
    urlString =
        [NSString stringWithFormat:kARDRoomServerJoinFormat, roomId];
  }

  NSURL *roomURL = [NSURL URLWithString:urlString];
  RTCLog(@"Joining room:%@ on room server.", roomId);
  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:roomURL];
  request.HTTPMethod = @"POST";
  __weak ARDAppEngineClient *weakSelf = self;
  [NSURLConnection sendAsyncRequest:request
                  completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                    if (error) {
                      if (completionHandler) {
                        completionHandler(nil, error);
                      }
                      return;
                    }
                    ARDJoinResponse *joinResponse = [ARDJoinResponse responseFromJSONData:data];
                    if (!joinResponse) {
                      if (completionHandler) {
                        NSError *error = [[self class] badResponseError];
                        completionHandler(nil, error);
                      }
                      return;
                    }
                    if (completionHandler) {
                      completionHandler(joinResponse, nil);
                    }
                  }];
}

- (void)sendMessage:(ARDSignalingMessage *)message
            forRoomId:(NSString *)roomId
             clientId:(NSString *)clientId
    completionHandler:(void (^)(ARDMessageResponse *response,
                                NSError *error))completionHandler {
  NSParameterAssert(message);
  NSParameterAssert(roomId.length);
  NSParameterAssert(clientId.length);

  NSData *data = [message JSONData];
  NSString *urlString =
      [NSString stringWithFormat:
          kARDRoomServerMessageFormat, roomId, clientId];
  NSURL *url = [NSURL URLWithString:urlString];
  RTCLog(@"C->RS POST: %@", message);
  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
  request.HTTPMethod = @"POST";
  request.HTTPBody = data;
  __weak ARDAppEngineClient *weakSelf = self;
  [NSURLConnection sendAsyncRequest:request
                  completionHandler:^(NSURLResponse *response,
                                      NSData *data,
                                      NSError *error) {
    if (error) {
      if (completionHandler) {
        completionHandler(nil, error);
      }
      return;
    }
    ARDMessageResponse *messageResponse =
        [ARDMessageResponse responseFromJSONData:data];
    if (!messageResponse) {
      if (completionHandler) {
        NSError *error = [[self class] badResponseError];
        completionHandler(nil, error);
      }
      return;
    }
    if (completionHandler) {
      completionHandler(messageResponse, nil);
    }
  }];
}

- (void)leaveRoomWithRoomId:(NSString *)roomId
                   clientId:(NSString *)clientId
          completionHandler:(void (^)(NSError *error))completionHandler {
  NSParameterAssert(roomId.length);
  NSParameterAssert(clientId.length);

  NSString *urlString =
      [NSString stringWithFormat:kARDRoomServerLeaveFormat, roomId, clientId];
  NSURL *url = [NSURL URLWithString:urlString];
  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
  request.HTTPMethod = @"POST";

  RTCLog(@"C->RS: BYE");
  __block NSError *error = nil;

  // We want a synchronous request so that we know that we've left the room on
  // room server before we do any further work.
  dispatch_semaphore_t sem = dispatch_semaphore_create(0);
  [NSURLConnection sendAsyncRequest:request
                  completionHandler:^(NSURLResponse *response, NSData *data, NSError *e) {
                    if (e) {
                      error = e;
                    }
                    dispatch_semaphore_signal(sem);
                  }];

  dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
  if (error) {
    RTCLogError(@"Error leaving room %@ on room server: %@", roomId, error.localizedDescription);
    if (completionHandler) {
      completionHandler(error);
    }
    return;
  }
  RTCLog(@"Left room:%@ on room server.", roomId);
  if (completionHandler) {
    completionHandler(nil);
  }
}

#pragma mark - Private

+ (NSError *)badResponseError {
  NSError *error =
      [[NSError alloc] initWithDomain:kARDAppEngineClientErrorDomain
                                 code:kARDAppEngineClientErrorBadResponse
                             userInfo:@{
    NSLocalizedDescriptionKey: @"Error parsing response.",
  }];
  return error;
}

@end
