/*
 * libjingle
 * Copyright 2014 Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif

#import "RTCDataChannel+Internal.h"

#include "talk/app/webrtc/datachannelinterface.h"

namespace webrtc {

class RTCDataChannelObserver : public DataChannelObserver {
 public:
  RTCDataChannelObserver(RTCDataChannel* channel) { _channel = channel; }

  void OnStateChange() override {
    [_channel.delegate channelDidChangeState:_channel];
  }

  void OnBufferedAmountChange(uint64 previousAmount) override {
    RTCDataChannel* channel = _channel;
    id<RTCDataChannelDelegate> delegate = channel.delegate;
    if ([delegate
            respondsToSelector:@selector(channel:didChangeBufferedAmount:)]) {
      [delegate channel:channel didChangeBufferedAmount:previousAmount];
    }
  }

  void OnMessage(const DataBuffer& buffer) override {
    if (!_channel.delegate) {
      return;
    }
    RTCDataBuffer* dataBuffer =
        [[RTCDataBuffer alloc] initWithDataBuffer:buffer];
    [_channel.delegate channel:_channel didReceiveMessageWithBuffer:dataBuffer];
  }

 private:
  __weak RTCDataChannel* _channel;
};
}

// TODO(henrika): move to shared location.
// See https://code.google.com/p/webrtc/issues/detail?id=4773 for details.
NSString* NSStringFromStdString(const std::string& stdString) {
  // std::string may contain null termination character so we construct
  // using length.
  return [[NSString alloc] initWithBytes:stdString.data()
                                  length:stdString.length()
                                encoding:NSUTF8StringEncoding];
}

std::string StdStringFromNSString(NSString* nsString) {
  NSData* charData = [nsString dataUsingEncoding:NSUTF8StringEncoding];
  return std::string(reinterpret_cast<const char*>([charData bytes]),
                     [charData length]);
}

@implementation RTCDataChannelInit {
  webrtc::DataChannelInit _dataChannelInit;
}

- (BOOL)isOrdered {
  return _dataChannelInit.ordered;
}

- (void)setIsOrdered:(BOOL)isOrdered {
  _dataChannelInit.ordered = isOrdered;
}

- (NSInteger)maxRetransmitTime {
  return _dataChannelInit.maxRetransmitTime;
}

- (void)setMaxRetransmitTime:(NSInteger)maxRetransmitTime {
  _dataChannelInit.maxRetransmitTime = maxRetransmitTime;
}

- (NSInteger)maxRetransmits {
  return _dataChannelInit.maxRetransmits;
}

- (void)setMaxRetransmits:(NSInteger)maxRetransmits {
  _dataChannelInit.maxRetransmits = maxRetransmits;
}

- (NSString*)protocol {
  return NSStringFromStdString(_dataChannelInit.protocol);
}

- (void)setProtocol:(NSString*)protocol {
  _dataChannelInit.protocol = StdStringFromNSString(protocol);
}

- (BOOL)isNegotiated {
  return _dataChannelInit.negotiated;
}

- (void)setIsNegotiated:(BOOL)isNegotiated {
  _dataChannelInit.negotiated = isNegotiated;
}

- (NSInteger)streamId {
  return _dataChannelInit.id;
}

- (void)setStreamId:(NSInteger)streamId {
  _dataChannelInit.id = streamId;
}

@end

@implementation RTCDataChannelInit (Internal)

- (const webrtc::DataChannelInit*)dataChannelInit {
  return &_dataChannelInit;
}

@end

@implementation RTCDataBuffer {
  rtc::scoped_ptr<webrtc::DataBuffer> _dataBuffer;
}

- (instancetype)initWithData:(NSData*)data isBinary:(BOOL)isBinary {
  NSAssert(data, @"data cannot be nil");
  if (self = [super init]) {
    rtc::Buffer buffer(reinterpret_cast<const uint8_t*>([data bytes]),
                       [data length]);
    _dataBuffer.reset(new webrtc::DataBuffer(buffer, isBinary));
  }
  return self;
}

- (NSData*)data {
  return [NSData dataWithBytes:_dataBuffer->data.data()
                        length:_dataBuffer->data.size()];
}

- (BOOL)isBinary {
  return _dataBuffer->binary;
}

@end

@implementation RTCDataBuffer (Internal)

- (instancetype)initWithDataBuffer:(const webrtc::DataBuffer&)buffer {
  if (self = [super init]) {
    _dataBuffer.reset(new webrtc::DataBuffer(buffer));
  }
  return self;
}

- (const webrtc::DataBuffer*)dataBuffer {
  return _dataBuffer.get();
}

@end

@implementation RTCDataChannel {
  rtc::scoped_refptr<webrtc::DataChannelInterface> _dataChannel;
  rtc::scoped_ptr<webrtc::RTCDataChannelObserver> _observer;
  BOOL _isObserverRegistered;
}

- (void)dealloc {
  // Handles unregistering the observer properly. We need to do this because
  // there may still be other references to the underlying data channel.
  self.delegate = nil;
}

- (NSString*)label {
  return NSStringFromStdString(_dataChannel->label());
}

- (BOOL)isReliable {
  return _dataChannel->reliable();
}

- (BOOL)isOrdered {
  return _dataChannel->ordered();
}

- (NSUInteger)maxRetransmitTimeMs {
  return _dataChannel->maxRetransmitTime();
}

- (NSUInteger)maxRetransmits {
  return _dataChannel->maxRetransmits();
}

- (NSString*)protocol {
  return NSStringFromStdString(_dataChannel->protocol());
}

- (BOOL)isNegotiated {
  return _dataChannel->negotiated();
}

- (NSInteger)streamId {
  return _dataChannel->id();
}

- (RTCDataChannelState)state {
  switch (_dataChannel->state()) {
    case webrtc::DataChannelInterface::DataState::kConnecting:
      return kRTCDataChannelStateConnecting;
    case webrtc::DataChannelInterface::DataState::kOpen:
      return kRTCDataChannelStateOpen;
    case webrtc::DataChannelInterface::DataState::kClosing:
      return kRTCDataChannelStateClosing;
    case webrtc::DataChannelInterface::DataState::kClosed:
      return kRTCDataChannelStateClosed;
  }
}

- (NSUInteger)bufferedAmount {
  return _dataChannel->buffered_amount();
}

- (void)setDelegate:(id<RTCDataChannelDelegate>)delegate {
  if (_delegate == delegate) {
    return;
  }
  if (_isObserverRegistered) {
    _dataChannel->UnregisterObserver();
    _isObserverRegistered = NO;
  }
  _delegate = delegate;
  if (_delegate) {
    _dataChannel->RegisterObserver(_observer.get());
    _isObserverRegistered = YES;
  }
}

- (void)close {
  _dataChannel->Close();
}

- (BOOL)sendData:(RTCDataBuffer*)data {
  return _dataChannel->Send(*data.dataBuffer);
}

@end

@implementation RTCDataChannel (Internal)

- (instancetype)initWithDataChannel:
                    (rtc::scoped_refptr<webrtc::DataChannelInterface>)
                dataChannel {
  NSAssert(dataChannel != NULL, @"dataChannel cannot be NULL");
  if (self = [super init]) {
    _dataChannel = dataChannel;
    _observer.reset(new webrtc::RTCDataChannelObserver(self));
  }
  return self;
}

- (rtc::scoped_refptr<webrtc::DataChannelInterface>)dataChannel {
  return _dataChannel;
}

@end
