/*
 *  Copyright 2017 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 "RTCEncodedImage+Private.h"

#import <objc/runtime.h>

#include "rtc_base/numerics/safe_conversions.h"

namespace {
// An implementation of EncodedImageBufferInterface that doesn't perform any
// copies.
class ObjCEncodedImageBuffer : public webrtc::EncodedImageBufferInterface {
 public:
  static rtc::scoped_refptr<ObjCEncodedImageBuffer> Create(NSData *data) {
    return rtc::make_ref_counted<ObjCEncodedImageBuffer>(data);
  }
  const uint8_t *data() const override {
    return static_cast<const uint8_t *>(data_.bytes);
  }
  // TODO(bugs.webrtc.org/9378): delete this non-const data method.
  uint8_t *data() override {
    return const_cast<uint8_t *>(static_cast<const uint8_t *>(data_.bytes));
  }
  size_t size() const override { return data_.length; }

 protected:
  explicit ObjCEncodedImageBuffer(NSData *data) : data_(data) {}
  ~ObjCEncodedImageBuffer() {}

  NSData *data_;
};
}  // namespace

// A simple wrapper around webrtc::EncodedImageBufferInterface to make it usable
// with associated objects.
@interface RTCWrappedEncodedImageBuffer : NSObject
@property(nonatomic) rtc::scoped_refptr<webrtc::EncodedImageBufferInterface>
    buffer;
- (instancetype)initWithEncodedImageBuffer:
    (rtc::scoped_refptr<webrtc::EncodedImageBufferInterface>)buffer;
@end
@implementation RTCWrappedEncodedImageBuffer
@synthesize buffer = _buffer;
- (instancetype)initWithEncodedImageBuffer:
    (rtc::scoped_refptr<webrtc::EncodedImageBufferInterface>)buffer {
  self = [super init];
  if (self) {
    _buffer = buffer;
  }
  return self;
}
@end

@implementation RTC_OBJC_TYPE (RTCEncodedImage)
(Private)

    - (rtc::scoped_refptr<webrtc::EncodedImageBufferInterface>)encodedData {
  RTCWrappedEncodedImageBuffer *wrappedBuffer =
      objc_getAssociatedObject(self, @selector(encodedData));
  return wrappedBuffer.buffer;
}

- (void)setEncodedData:
    (rtc::scoped_refptr<webrtc::EncodedImageBufferInterface>)buffer {
  return objc_setAssociatedObject(
      self,
      @selector(encodedData),
      [[RTCWrappedEncodedImageBuffer alloc] initWithEncodedImageBuffer:buffer],
      OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (instancetype)initWithNativeEncodedImage:
    (const webrtc::EncodedImage &)encodedImage {
  self = [super init];
  if (self) {
    // A reference to the encodedData must be stored so that it's kept alive as
    // long self.buffer references its underlying data.
    self.encodedData = encodedImage.GetEncodedData();
    // Wrap the buffer in NSData without copying, do not take ownership.
    self.buffer = [NSData dataWithBytesNoCopy:self.encodedData->data()
                                       length:encodedImage.size()
                                 freeWhenDone:NO];
    self.encodedWidth = rtc::dchecked_cast<int32_t>(encodedImage._encodedWidth);
    self.encodedHeight =
        rtc::dchecked_cast<int32_t>(encodedImage._encodedHeight);
    self.timeStamp = encodedImage.RtpTimestamp();
    self.captureTimeMs = encodedImage.capture_time_ms_;
    self.ntpTimeMs = encodedImage.ntp_time_ms_;
    self.flags = encodedImage.timing_.flags;
    self.encodeStartMs = encodedImage.timing_.encode_start_ms;
    self.encodeFinishMs = encodedImage.timing_.encode_finish_ms;
    self.frameType = static_cast<RTCFrameType>(encodedImage._frameType);
    self.rotation = static_cast<RTCVideoRotation>(encodedImage.rotation_);
    self.qp = @(encodedImage.qp_);
    self.contentType =
        (encodedImage.content_type_ == webrtc::VideoContentType::SCREENSHARE) ?
        RTCVideoContentTypeScreenshare :
        RTCVideoContentTypeUnspecified;
  }

  return self;
}

- (webrtc::EncodedImage)nativeEncodedImage {
  // Return the pointer without copying.
  webrtc::EncodedImage encodedImage;
  if (self.encodedData) {
    encodedImage.SetEncodedData(self.encodedData);
  } else if (self.buffer) {
    encodedImage.SetEncodedData(ObjCEncodedImageBuffer::Create(self.buffer));
  }
  encodedImage.set_size(self.buffer.length);
  encodedImage._encodedWidth = rtc::dchecked_cast<uint32_t>(self.encodedWidth);
  encodedImage._encodedHeight =
      rtc::dchecked_cast<uint32_t>(self.encodedHeight);
  encodedImage.SetRtpTimestamp(self.timeStamp);
  encodedImage.capture_time_ms_ = self.captureTimeMs;
  encodedImage.ntp_time_ms_ = self.ntpTimeMs;
  encodedImage.timing_.flags = self.flags;
  encodedImage.timing_.encode_start_ms = self.encodeStartMs;
  encodedImage.timing_.encode_finish_ms = self.encodeFinishMs;
  encodedImage._frameType = webrtc::VideoFrameType(self.frameType);
  encodedImage.rotation_ = webrtc::VideoRotation(self.rotation);
  encodedImage.qp_ = self.qp ? self.qp.intValue : -1;
  encodedImage.content_type_ =
      (self.contentType == RTCVideoContentTypeScreenshare) ?
      webrtc::VideoContentType::SCREENSHARE :
      webrtc::VideoContentType::UNSPECIFIED;

  return encodedImage;
}

@end
