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

#import "sdk/objc/base/RTCLogging.h"

#import "ARDUtilities.h"
#import "RTCIceCandidate+JSON.h"
#import "RTCSessionDescription+JSON.h"

static NSString *const kARDSignalingMessageTypeKey = @"type";
static NSString *const kARDTypeValueRemoveCandidates = @"remove-candidates";

@implementation ARDSignalingMessage

@synthesize type = _type;

- (instancetype)initWithType:(ARDSignalingMessageType)type {
  self = [super init];
  if (self) {
    _type = type;
  }
  return self;
}

- (NSString *)description {
  return [[NSString alloc] initWithData:[self JSONData]
                               encoding:NSUTF8StringEncoding];
}

+ (ARDSignalingMessage *)messageFromJSONString:(NSString *)jsonString {
  NSDictionary *values = [NSDictionary dictionaryWithJSONString:jsonString];
  if (!values) {
    RTCLogError(@"Error parsing signaling message JSON.");
    return nil;
  }

  NSString *typeString = values[kARDSignalingMessageTypeKey];
  ARDSignalingMessage *message = nil;
  if ([typeString isEqualToString:@"candidate"]) {
    RTC_OBJC_TYPE(RTCIceCandidate) *candidate =
        [RTC_OBJC_TYPE(RTCIceCandidate) candidateFromJSONDictionary:values];
    message = [[ARDICECandidateMessage alloc] initWithCandidate:candidate];
  } else if ([typeString isEqualToString:kARDTypeValueRemoveCandidates]) {
    RTCLogInfo(@"Received remove-candidates message");
    NSArray<RTC_OBJC_TYPE(RTCIceCandidate) *> *candidates =
        [RTC_OBJC_TYPE(RTCIceCandidate) candidatesFromJSONDictionary:values];
    message = [[ARDICECandidateRemovalMessage alloc]
        initWithRemovedCandidates:candidates];
  } else if ([typeString isEqualToString:@"offer"] ||
             [typeString isEqualToString:@"answer"]) {
    RTC_OBJC_TYPE(RTCSessionDescription) *description =
        [RTC_OBJC_TYPE(RTCSessionDescription)
            descriptionFromJSONDictionary:values];
    message =
        [[ARDSessionDescriptionMessage alloc] initWithDescription:description];
  } else if ([typeString isEqualToString:@"bye"]) {
    message = [[ARDByeMessage alloc] init];
  } else {
    RTCLogError(@"Unexpected type: %@", typeString);
  }
  return message;
}

- (NSData *)JSONData {
  return nil;
}

@end

@implementation ARDICECandidateMessage

@synthesize candidate = _candidate;

- (instancetype)initWithCandidate:(RTC_OBJC_TYPE(RTCIceCandidate) *)candidate {
  self = [super initWithType:kARDSignalingMessageTypeCandidate];
  if (self) {
    _candidate = candidate;
  }
  return self;
}

- (NSData *)JSONData {
  return [_candidate JSONData];
}

@end

@implementation ARDICECandidateRemovalMessage

@synthesize candidates = _candidates;

- (instancetype)initWithRemovedCandidates:
    (NSArray<RTC_OBJC_TYPE(RTCIceCandidate) *> *)candidates {
  NSParameterAssert(candidates.count);
  self = [super initWithType:kARDSignalingMessageTypeCandidateRemoval];
  if (self) {
    _candidates = candidates;
  }
  return self;
}

- (NSData *)JSONData {
  return [RTC_OBJC_TYPE(RTCIceCandidate)
      JSONDataForIceCandidates:_candidates
                      withType:kARDTypeValueRemoveCandidates];
}

@end

@implementation ARDSessionDescriptionMessage

@synthesize sessionDescription = _sessionDescription;

- (instancetype)initWithDescription:
    (RTC_OBJC_TYPE(RTCSessionDescription) *)description {
  ARDSignalingMessageType messageType = kARDSignalingMessageTypeOffer;
  RTCSdpType sdpType = description.type;
  switch (sdpType) {
    case RTCSdpTypeOffer:
      messageType = kARDSignalingMessageTypeOffer;
      break;
    case RTCSdpTypeAnswer:
      messageType = kARDSignalingMessageTypeAnswer;
      break;
    case RTCSdpTypePrAnswer:
    case RTCSdpTypeRollback:
      NSAssert(NO,
               @"Unexpected type: %@",
               [RTC_OBJC_TYPE(RTCSessionDescription) stringForType:sdpType]);
      break;
  }
  self = [super initWithType:messageType];
  if (self) {
    _sessionDescription = description;
  }
  return self;
}

- (NSData *)JSONData {
  return [_sessionDescription JSONData];
}

@end

@implementation ARDByeMessage

- (instancetype)init {
  return [super initWithType:kARDSignalingMessageTypeBye];
}

- (NSData *)JSONData {
  NSDictionary *message = @{@"type" : @"bye"};
  return [NSJSONSerialization dataWithJSONObject:message
                                         options:NSJSONWritingPrettyPrinted
                                           error:NULL];
}

@end
