/*
 *  Copyright (c) 2013 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.
 */

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

#include <AVFoundation/AVFoundation.h>

#include <string>

#include "webrtc/modules/video_capture/ios/device_info_ios.h"
#include "webrtc/modules/video_capture/ios/device_info_ios_objc.h"
#include "webrtc/modules/video_capture/video_capture_impl.h"
#include "webrtc/system_wrappers/include/trace.h"

using namespace webrtc;
using namespace videocapturemodule;

static NSArray *camera_presets = @[AVCaptureSessionPreset352x288,
                                   AVCaptureSessionPreset640x480,
                                   AVCaptureSessionPreset1280x720,
                                   AVCaptureSessionPreset1920x1080];


#define IOS_UNSUPPORTED()                                  \
  WEBRTC_TRACE(kTraceError,                                \
               kTraceVideoCapture,                         \
               _id,                                        \
               "%s is not supported on the iOS platform.", \
               __FUNCTION__);                              \
  return -1;

VideoCaptureModule::DeviceInfo* VideoCaptureImpl::CreateDeviceInfo(
    const int32_t device_id) {
  return new DeviceInfoIos(device_id);
}

DeviceInfoIos::DeviceInfoIos(const int32_t device_id)
    : DeviceInfoImpl(device_id) {
  this->Init();
}

DeviceInfoIos::~DeviceInfoIos() {}

int32_t DeviceInfoIos::Init() {
  // Fill in all device capabilities.

  int deviceCount = [DeviceInfoIosObjC captureDeviceCount];

  for (int i = 0; i < deviceCount; i++) {
    AVCaptureDevice *avDevice = [DeviceInfoIosObjC captureDeviceForIndex:i];
    VideoCaptureCapabilities capabilityVector;

    for (NSString *preset in camera_presets) {
      BOOL support = [avDevice supportsAVCaptureSessionPreset:preset];
      if (support) {
        VideoCaptureCapability capability =
            [DeviceInfoIosObjC capabilityForPreset:preset];
        capabilityVector.push_back(capability);
      }
    }

    char deviceNameUTF8[256];
    char deviceId[256];
    this->GetDeviceName(i, deviceNameUTF8, 256, deviceId, 256);
    std::string deviceIdCopy(deviceId);
    std::pair<std::string, VideoCaptureCapabilities> mapPair =
        std::pair<std::string, VideoCaptureCapabilities>
            (deviceIdCopy, capabilityVector);
    _capabilitiesMap.insert(mapPair);
  }

  return 0;
}

uint32_t DeviceInfoIos::NumberOfDevices() {
  return [DeviceInfoIosObjC captureDeviceCount];
}

int32_t DeviceInfoIos::GetDeviceName(uint32_t deviceNumber,
                                     char* deviceNameUTF8,
                                     uint32_t deviceNameUTF8Length,
                                     char* deviceUniqueIdUTF8,
                                     uint32_t deviceUniqueIdUTF8Length,
                                     char* productUniqueIdUTF8,
                                     uint32_t productUniqueIdUTF8Length) {
  NSString* deviceName = [DeviceInfoIosObjC deviceNameForIndex:deviceNumber];

  NSString* deviceUniqueId =
      [DeviceInfoIosObjC deviceUniqueIdForIndex:deviceNumber];

  strncpy(deviceNameUTF8, [deviceName UTF8String], deviceNameUTF8Length);
  deviceNameUTF8[deviceNameUTF8Length - 1] = '\0';

  strncpy(deviceUniqueIdUTF8,
          [deviceUniqueId UTF8String],
          deviceUniqueIdUTF8Length);
  deviceUniqueIdUTF8[deviceUniqueIdUTF8Length - 1] = '\0';

  if (productUniqueIdUTF8) {
    productUniqueIdUTF8[0] = '\0';
  }

  return 0;
}

int32_t DeviceInfoIos::NumberOfCapabilities(const char* deviceUniqueIdUTF8) {
  int32_t numberOfCapabilities = 0;
  std::string deviceUniqueId(deviceUniqueIdUTF8);
  std::map<std::string, VideoCaptureCapabilities>::iterator it =
      _capabilitiesMap.find(deviceUniqueId);

  if (it != _capabilitiesMap.end()) {
    numberOfCapabilities = it->second.size();
  }
  return numberOfCapabilities;
}

int32_t DeviceInfoIos::GetCapability(const char* deviceUniqueIdUTF8,
                                     const uint32_t deviceCapabilityNumber,
                                     VideoCaptureCapability& capability) {
  std::string deviceUniqueId(deviceUniqueIdUTF8);
  std::map<std::string, VideoCaptureCapabilities>::iterator it =
      _capabilitiesMap.find(deviceUniqueId);

  if (it != _capabilitiesMap.end()) {
    VideoCaptureCapabilities deviceCapabilities = it->second;

    if (deviceCapabilityNumber < deviceCapabilities.size()) {
      VideoCaptureCapability cap;
      cap = deviceCapabilities[deviceCapabilityNumber];
      capability = cap;
      return 0;
    }
  }

  return -1;
}

int32_t DeviceInfoIos::DisplayCaptureSettingsDialogBox(
    const char* deviceUniqueIdUTF8,
    const char* dialogTitleUTF8,
    void* parentWindow,
    uint32_t positionX,
    uint32_t positionY) {
  IOS_UNSUPPORTED();
}

int32_t DeviceInfoIos::GetOrientation(const char* deviceUniqueIdUTF8,
                                      VideoRotation& orientation) {
  if (strcmp(deviceUniqueIdUTF8, "Front Camera") == 0) {
    orientation = kVideoRotation_0;
  } else {
    orientation = kVideoRotation_90;
  }
  return orientation;
}

int32_t DeviceInfoIos::CreateCapabilityMap(const char* deviceUniqueIdUTF8) {
  std::string deviceName(deviceUniqueIdUTF8);
  std::map<std::string, std::vector<VideoCaptureCapability>>::iterator it =
      _capabilitiesMap.find(deviceName);
  VideoCaptureCapabilities deviceCapabilities;
  if (it != _capabilitiesMap.end()) {
    _captureCapabilities = it->second;
    return 0;
  }

  return -1;
}
