/*
 *  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_;
};
}

// 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
