/*
 *  Copyright 2016 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 <Foundation/Foundation.h>
#import <OCMock/OCMock.h>

#include "rtc_base/gunit.h"

// Width and height don't play any role so lets use predefined values throughout
// the tests.
static const int kFormatWidth = 789;
static const int kFormatHeight = 987;

// Hardcoded framrate to be used throughout the tests.
static const int kFramerate = 30;

// Same width and height is used so it's ok to expect same cricket::VideoFormat
static cricket::VideoFormat expectedFormat =
    cricket::VideoFormat(kFormatWidth,
                         kFormatHeight,
                         cricket::VideoFormat::FpsToInterval(kFramerate),
                         cricket::FOURCC_NV12);

// Mock class for AVCaptureDeviceFormat.
// Custom implementation needed because OCMock cannot handle the
// CMVideoDescriptionRef mocking.
@interface AVCaptureDeviceFormatMock : NSObject

@property (nonatomic, assign) CMVideoFormatDescriptionRef format;
@property (nonatomic, strong) OCMockObject *rangeMock;

- (instancetype)initWithMediaSubtype:(FourCharCode)subtype
                              minFps:(float)minFps
                              maxFps:(float)maxFps;
+ (instancetype)validFormat;
+ (instancetype)invalidFpsFormat;
+ (instancetype)invalidMediaSubtypeFormat;

@end

@implementation AVCaptureDeviceFormatMock

@synthesize format = _format;
@synthesize rangeMock = _rangeMock;

- (instancetype)initWithMediaSubtype:(FourCharCode)subtype
                              minFps:(float)minFps
                              maxFps:(float)maxFps {
  self = [super init];
  if (self) {
    CMVideoFormatDescriptionCreate(nil, subtype, kFormatWidth, kFormatHeight,
                                   nil, &_format);
    // We can use OCMock for the range.
    _rangeMock = [OCMockObject mockForClass:[AVFrameRateRange class]];
    [[[_rangeMock stub] andReturnValue:@(minFps)] minFrameRate];
    [[[_rangeMock stub] andReturnValue:@(maxFps)] maxFrameRate];
  }

  return self;
}

+ (instancetype)validFormat {
  AVCaptureDeviceFormatMock *instance = [[AVCaptureDeviceFormatMock alloc]
      initWithMediaSubtype:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
                    minFps:0.0
                    maxFps:30.0];
  return instance;
}

+ (instancetype)invalidFpsFormat {
  AVCaptureDeviceFormatMock *instance = [[AVCaptureDeviceFormatMock alloc]
      initWithMediaSubtype:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
                    minFps:0.0
                    maxFps:22.0];
  return instance;
}

+ (instancetype)invalidMediaSubtypeFormat {
  AVCaptureDeviceFormatMock *instance = [[AVCaptureDeviceFormatMock alloc]
      initWithMediaSubtype:kCVPixelFormatType_420YpCbCr8Planar
                    minFps:0.0
                    maxFps:60.0];
  return instance;
}

- (void)dealloc {
  if (_format != nil) {
    CFRelease(_format);
    _format = nil;
  }
}

// Redefinition of AVCaptureDevice methods we want to mock.
- (CMVideoFormatDescriptionRef)formatDescription {
  return self.format;
}

- (NSArray *)videoSupportedFrameRateRanges {
  return @[ self.rangeMock ];
}

@end

TEST(AVFormatMapperTest, SuportedCricketFormatsWithInvalidFramerateFormats) {
  // given
  id mockDevice = OCMClassMock([AVCaptureDevice class]);

  // Valid media subtype, invalid framerate
  AVCaptureDeviceFormatMock* mock =
      [AVCaptureDeviceFormatMock invalidFpsFormat];
  OCMStub([mockDevice formats]).andReturn(@[ mock ]);

  // when
  std::set<cricket::VideoFormat> result =
      webrtc::GetSupportedVideoFormatsForDevice(mockDevice);

  // then
  EXPECT_TRUE(result.empty());
}

TEST(AVFormatMapperTest, SuportedCricketFormatsWithInvalidFormats) {
  // given
  id mockDevice = OCMClassMock([AVCaptureDevice class]);

  // Invalid media subtype, valid framerate
  AVCaptureDeviceFormatMock* mock =
      [AVCaptureDeviceFormatMock invalidMediaSubtypeFormat];
  OCMStub([mockDevice formats]).andReturn(@[ mock ]);

  // when
  std::set<cricket::VideoFormat> result =
      webrtc::GetSupportedVideoFormatsForDevice(mockDevice);

  // then
  EXPECT_TRUE(result.empty());
}

TEST(AVFormatMapperTest, SuportedCricketFormats) {
  // given
  id mockDevice = OCMClassMock([AVCaptureDevice class]);

  // valid media subtype, valid framerate
  AVCaptureDeviceFormatMock* mock = [AVCaptureDeviceFormatMock validFormat];
  OCMStub([mockDevice formats]).andReturn(@[ mock ]);

  // when
  std::set<cricket::VideoFormat> result =
      webrtc::GetSupportedVideoFormatsForDevice(mockDevice);

  // then
  EXPECT_EQ(1u, result.size());
  // make sure the set has the expected format
  EXPECT_EQ(expectedFormat, *result.begin());
}

TEST(AVFormatMapperTest, MediaSubtypePreference) {
  // given
  id mockDevice = OCMClassMock([AVCaptureDevice class]);

  // valid media subtype, valid framerate
  AVCaptureDeviceFormatMock* mockOne = [[AVCaptureDeviceFormatMock alloc]
      initWithMediaSubtype:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
                    minFps:0.0
                    maxFps:30.0];
  // valid media subtype, valid framerate.
  // This media subtype should be the preffered one.
  AVCaptureDeviceFormatMock* mockTwo = [[AVCaptureDeviceFormatMock alloc]
      initWithMediaSubtype:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange
                    minFps:0.0
                    maxFps:30.0];
  OCMStub([mockDevice lockForConfiguration:[OCMArg setTo:nil]]).andReturn(YES);
  OCMStub([mockDevice unlockForConfiguration]);
  NSArray* array = @[ mockOne, mockTwo ];
  OCMStub([mockDevice formats]).andReturn(array);

  // to verify
  OCMExpect([mockDevice setActiveFormat:(AVCaptureDeviceFormat*)mockTwo]);
  OCMExpect(
      [mockDevice setActiveVideoMinFrameDuration:CMTimeMake(1, kFramerate)]);

  // when
  bool resultFormat =
      webrtc::SetFormatForCaptureDevice(mockDevice, nil, expectedFormat);

  // then
  EXPECT_TRUE(resultFormat);
  [mockDevice verify];
}

TEST(AVFormatMapperTest, SetFormatWhenDeviceCannotLock) {
  // given
  id mockDevice = OCMClassMock([AVCaptureDevice class]);
  [[[mockDevice stub] andReturnValue:@(NO)]
      lockForConfiguration:[OCMArg setTo:nil]];
  [[[mockDevice stub] andReturn:@[]] formats];

  // when
  bool resultFormat = webrtc::SetFormatForCaptureDevice(mockDevice, nil,
                                                        cricket::VideoFormat());

  // then
  EXPECT_FALSE(resultFormat);
}

TEST(AVFormatMapperTest, SetFormatWhenFormatIsIncompatible) {
  // given
  id mockDevice = OCMClassMock([AVCaptureDevice class]);
  OCMStub([mockDevice formats]).andReturn(@[]);
  OCMStub([mockDevice lockForConfiguration:[OCMArg setTo:nil]]).andReturn(YES);
  NSException* testException =
      [NSException exceptionWithName:@"Test exception"
                              reason:@"Raised from unit tests"
                            userInfo:nil];
  OCMStub([mockDevice setActiveFormat:[OCMArg any]]).andThrow(testException);
  OCMExpect([mockDevice unlockForConfiguration]);

  // when
  bool resultFormat = webrtc::SetFormatForCaptureDevice(mockDevice, nil,
                                                        cricket::VideoFormat());

  // then
  EXPECT_FALSE(resultFormat);

  // TODO(denicija): Remove try-catch when Chromium rolls this change:
  // https://github.com/erikdoe/ocmock/commit/de1419415581dc307045e54bfe9c98c86efea96b
  // Without it, stubbed exceptions are being re-raised on [mock verify].
  // More information here:
  //https://github.com/erikdoe/ocmock/issues/241
  @try {
    [mockDevice verify];
  } @catch (NSException* exception) {
    if ([exception.reason isEqual:testException.reason]) {
      // Nothing dangerous here
      EXPECT_TRUE([exception.reason isEqualToString:exception.reason]);
    }
  }
}
