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

#include "webrtc/video_engine/vie_capture_impl.h"

#include <map>

#include "webrtc/system_wrappers/interface/logging.h"
#include "webrtc/video_engine/include/vie_errors.h"
#include "webrtc/video_engine/vie_capturer.h"
#include "webrtc/video_engine/vie_channel.h"
#include "webrtc/video_engine/vie_channel_manager.h"
#include "webrtc/video_engine/vie_defines.h"
#include "webrtc/video_engine/vie_encoder.h"
#include "webrtc/video_engine/vie_impl.h"
#include "webrtc/video_engine/vie_input_manager.h"
#include "webrtc/video_engine/vie_shared_data.h"

namespace webrtc {

class CpuOveruseObserver;

ViECapture* ViECapture::GetInterface(VideoEngine* video_engine) {
#ifdef WEBRTC_VIDEO_ENGINE_CAPTURE_API
  if (!video_engine) {
    return NULL;
  }
  VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine);
  ViECaptureImpl* vie_capture_impl = vie_impl;
  // Increase ref count.
  (*vie_capture_impl)++;
  return vie_capture_impl;
#else
  return NULL;
#endif
}

int ViECaptureImpl::Release() {
  // Decrease ref count
  (*this)--;

  int32_t ref_count = GetCount();
  if (ref_count < 0) {
    LOG(LS_WARNING) << "ViECapture released too many times.";
    shared_data_->SetLastError(kViEAPIDoesNotExist);
    return -1;
  }
  return ref_count;
}

ViECaptureImpl::ViECaptureImpl(ViESharedData* shared_data)
    : shared_data_(shared_data) {}

ViECaptureImpl::~ViECaptureImpl() {}

int ViECaptureImpl::NumberOfCaptureDevices() {
  return  shared_data_->input_manager()->NumberOfCaptureDevices();
}


int ViECaptureImpl::GetCaptureDevice(unsigned int list_number,
                                     char* device_nameUTF8,
                                     unsigned int device_nameUTF8Length,
                                     char* unique_idUTF8,
                                     unsigned int unique_idUTF8Length) {
  return shared_data_->input_manager()->GetDeviceName(
      list_number,
      device_nameUTF8, device_nameUTF8Length,
      unique_idUTF8, unique_idUTF8Length);
}

int ViECaptureImpl::AllocateCaptureDevice(
  const char* unique_idUTF8,
  const unsigned int unique_idUTF8Length,
  int& capture_id) {
  LOG(LS_INFO) << "AllocateCaptureDevice " << unique_idUTF8;
  const int32_t result =
      shared_data_->input_manager()->CreateCaptureDevice(
          unique_idUTF8,
          static_cast<const uint32_t>(unique_idUTF8Length),
          capture_id);
  if (result != 0) {
    shared_data_->SetLastError(result);
    return -1;
  }
  return 0;
}

int ViECaptureImpl::AllocateExternalCaptureDevice(
  int& capture_id, ViEExternalCapture*& external_capture) {
  const int32_t result =
      shared_data_->input_manager()->CreateExternalCaptureDevice(
          external_capture, capture_id);

  if (result != 0) {
    shared_data_->SetLastError(result);
    return -1;
  }
  LOG(LS_INFO) << "External capture device allocated: " << capture_id;
  return 0;
}

int ViECaptureImpl::AllocateCaptureDevice(
    VideoCaptureModule& capture_module, int& capture_id) {  // NOLINT
  int32_t result = shared_data_->input_manager()->CreateCaptureDevice(
      &capture_module, capture_id);
  if (result != 0) {
    shared_data_->SetLastError(result);
    return -1;
  }
  LOG(LS_INFO) << "External capture device, by module, allocated: "
               << capture_id;
  return 0;
}


int ViECaptureImpl::ReleaseCaptureDevice(const int capture_id) {
  LOG(LS_INFO) << "ReleaseCaptureDevice " << capture_id;
  {
    ViEInputManagerScoped is((*(shared_data_->input_manager())));
    ViECapturer* vie_capture = is.Capture(capture_id);
    if (!vie_capture) {
      shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
      return -1;
    }
  }
  return shared_data_->input_manager()->DestroyCaptureDevice(capture_id);
}

int ViECaptureImpl::ConnectCaptureDevice(const int capture_id,
                                         const int video_channel) {
  LOG(LS_INFO) << "Connect capture id " << capture_id
               << " to channel " << video_channel;

  ViEInputManagerScoped is(*(shared_data_->input_manager()));
  ViECapturer* vie_capture = is.Capture(capture_id);
  if (!vie_capture) {
    shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
    return -1;
  }

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    LOG(LS_ERROR) << "Channel doesn't exist.";
    shared_data_->SetLastError(kViECaptureDeviceInvalidChannelId);
    return -1;
  }
  if (vie_encoder->Owner() != video_channel) {
    LOG(LS_ERROR) << "Can't connect capture device to a receive device.";
    shared_data_->SetLastError(kViECaptureDeviceInvalidChannelId);
    return -1;
  }
  //  Check if the encoder already has a connected frame provider
  if (is.FrameProvider(vie_encoder) != NULL) {
    LOG(LS_ERROR) << "Channel already connected to capture device.";
    shared_data_->SetLastError(kViECaptureDeviceAlreadyConnected);
    return -1;
  }
  if (vie_capture->RegisterFrameCallback(video_channel, vie_encoder) != 0) {
    shared_data_->SetLastError(kViECaptureDeviceUnknownError);
    return -1;
  }
  std::map<int, CpuOveruseObserver*>::iterator it =
      shared_data_->overuse_observers()->find(video_channel);
  if (it != shared_data_->overuse_observers()->end()) {
    vie_capture->RegisterCpuOveruseObserver(it->second);
  }
  return 0;
}


int ViECaptureImpl::DisconnectCaptureDevice(const int video_channel) {
  LOG(LS_INFO) << "DisconnectCaptureDevice " << video_channel;

  ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
  ViEEncoder* vie_encoder = cs.Encoder(video_channel);
  if (!vie_encoder) {
    LOG(LS_ERROR) << "Channel doesn't exist.";
    shared_data_->SetLastError(kViECaptureDeviceInvalidChannelId);
    return -1;
  }

  ViEInputManagerScoped is(*(shared_data_->input_manager()));
  ViEFrameProviderBase* frame_provider = is.FrameProvider(vie_encoder);
  if (!frame_provider) {
    shared_data_->SetLastError(kViECaptureDeviceNotConnected);
    return -1;
  }
  if (frame_provider->Id() < kViECaptureIdBase ||
      frame_provider->Id() > kViECaptureIdMax) {
    shared_data_->SetLastError(kViECaptureDeviceNotConnected);
    return -1;
  }

  ViECapturer* vie_capture = is.Capture(frame_provider->Id());
  assert(vie_capture);
  vie_capture->RegisterCpuOveruseObserver(NULL);
  if (frame_provider->DeregisterFrameCallback(vie_encoder) != 0) {
    shared_data_->SetLastError(kViECaptureDeviceUnknownError);
    return -1;
  }

  return 0;
}

int ViECaptureImpl::StartCapture(const int capture_id,
                                 const CaptureCapability& capture_capability) {
  LOG(LS_ERROR) << "StartCapture " << capture_id;

  ViEInputManagerScoped is(*(shared_data_->input_manager()));
  ViECapturer* vie_capture = is.Capture(capture_id);
  if (!vie_capture) {
    shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
    return -1;
  }
  if (vie_capture->Started()) {
    shared_data_->SetLastError(kViECaptureDeviceAlreadyStarted);
    return -1;
  }
  if (vie_capture->Start(capture_capability) != 0) {
    shared_data_->SetLastError(kViECaptureDeviceUnknownError);
    return -1;
  }
  return 0;
}

int ViECaptureImpl::StopCapture(const int capture_id) {
  LOG(LS_INFO) << "StopCapture " << capture_id;

  ViEInputManagerScoped is(*(shared_data_->input_manager()));
  ViECapturer* vie_capture = is.Capture(capture_id);
  if (!vie_capture) {
    shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
    return -1;
  }
  if (!vie_capture->Started()) {
    shared_data_->SetLastError(kViECaptureDeviceNotStarted);
    return 0;
  }
  if (vie_capture->Stop() != 0) {
    shared_data_->SetLastError(kViECaptureDeviceUnknownError);
    return -1;
  }
  return 0;
}

int ViECaptureImpl::SetRotateCapturedFrames(
    const int capture_id,
    const RotateCapturedFrame rotation) {
  int i_rotation = -1;
  switch (rotation) {
    case RotateCapturedFrame_0:
      i_rotation = 0;
      break;
    case RotateCapturedFrame_90:
      i_rotation = 90;
      break;
    case RotateCapturedFrame_180:
      i_rotation = 180;
      break;
    case RotateCapturedFrame_270:
      i_rotation = 270;
      break;
  }
  LOG(LS_INFO) << "SetRotateCaptureFrames for " << capture_id
               << ", rotation " << i_rotation;

  ViEInputManagerScoped is(*(shared_data_->input_manager()));
  ViECapturer* vie_capture = is.Capture(capture_id);
  if (!vie_capture) {
    shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
    return -1;
  }
  if (vie_capture->SetRotateCapturedFrames(rotation) != 0) {
    shared_data_->SetLastError(kViECaptureDeviceUnknownError);
    return -1;
  }
  return 0;
}

int ViECaptureImpl::SetCaptureDelay(const int capture_id,
                                    const unsigned int capture_delay_ms) {
  LOG(LS_INFO) << "SetCaptureDelay " << capture_delay_ms
               << ", for device " << capture_id;

  ViEInputManagerScoped is(*(shared_data_->input_manager()));
  ViECapturer* vie_capture = is.Capture(capture_id);
  if (!vie_capture) {
    shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
    return -1;
  }

  if (vie_capture->SetCaptureDelay(capture_delay_ms) != 0) {
    shared_data_->SetLastError(kViECaptureDeviceUnknownError);
    return -1;
  }
  return 0;
}

int ViECaptureImpl::NumberOfCapabilities(
    const char* unique_idUTF8,
    const unsigned int unique_idUTF8Length) {

#if defined(WEBRTC_MAC)
  // TODO(mflodman) Move to capture module!
  // QTKit framework handles all capabilities and capture settings
  // automatically (mandatory).
  // Thus this function cannot be supported on the Mac platform.
  shared_data_->SetLastError(kViECaptureDeviceMacQtkitNotSupported);
  LOG_F(LS_ERROR) << "API not supported on Mac OS X.";
  return -1;
#endif
  return shared_data_->input_manager()->NumberOfCaptureCapabilities(
      unique_idUTF8);
}


int ViECaptureImpl::GetCaptureCapability(const char* unique_idUTF8,
                                         const unsigned int unique_idUTF8Length,
                                         const unsigned int capability_number,
                                         CaptureCapability& capability) {

#if defined(WEBRTC_MAC)
  // TODO(mflodman) Move to capture module!
  // QTKit framework handles all capabilities and capture settings
  // automatically (mandatory).
  // Thus this function cannot be supported on the Mac platform.
  LOG_F(LS_ERROR) << "API not supported on Mac OS X.";
  shared_data_->SetLastError(kViECaptureDeviceMacQtkitNotSupported);
  return -1;
#endif
  if (shared_data_->input_manager()->GetCaptureCapability(
          unique_idUTF8, capability_number, capability) != 0) {
    shared_data_->SetLastError(kViECaptureDeviceUnknownError);
    return -1;
  }
  return 0;
}

int ViECaptureImpl::ShowCaptureSettingsDialogBox(
    const char* unique_idUTF8,
    const unsigned int unique_idUTF8Length,
    const char* dialog_title,
    void* parent_window,
    const unsigned int x,
    const unsigned int y) {
#if defined(WEBRTC_MAC)
  // TODO(mflodman) Move to capture module
  // QTKit framework handles all capabilities and capture settings
  // automatically (mandatory).
  // Thus this function cannot be supported on the Mac platform.
  shared_data_->SetLastError(kViECaptureDeviceMacQtkitNotSupported);
  LOG_F(LS_ERROR) << "API not supported on Mac OS X.";
  return -1;
#endif
  return shared_data_->input_manager()->DisplayCaptureSettingsDialogBox(
           unique_idUTF8, dialog_title,
           parent_window, x, y);
}

int ViECaptureImpl::GetOrientation(const char* unique_idUTF8,
                                   RotateCapturedFrame& orientation) {
  if (shared_data_->input_manager()->GetOrientation(
      unique_idUTF8,
      orientation) != 0) {
    shared_data_->SetLastError(kViECaptureDeviceUnknownError);
    return -1;
  }
  return 0;
}


int ViECaptureImpl::EnableBrightnessAlarm(const int capture_id,
                                          const bool enable) {
  LOG(LS_INFO) << "EnableBrightnessAlarm for device " << capture_id
               << ", status " << enable;
  ViEInputManagerScoped is(*(shared_data_->input_manager()));
  ViECapturer* vie_capture = is.Capture(capture_id);
  if (!vie_capture) {
    shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
    return -1;
  }
  if (vie_capture->EnableBrightnessAlarm(enable) != 0) {
    shared_data_->SetLastError(kViECaptureDeviceUnknownError);
    return -1;
  }
  return 0;
}

int ViECaptureImpl::RegisterObserver(const int capture_id,
                                     ViECaptureObserver& observer) {
  LOG(LS_INFO) << "Register capture observer " << capture_id;
  ViEInputManagerScoped is(*(shared_data_->input_manager()));
  ViECapturer* vie_capture = is.Capture(capture_id);
  if (!vie_capture) {
    shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
    return -1;
  }
  if (vie_capture->IsObserverRegistered()) {
    LOG_F(LS_ERROR) << "Observer already registered.";
    shared_data_->SetLastError(kViECaptureObserverAlreadyRegistered);
    return -1;
  }
  if (vie_capture->RegisterObserver(&observer) != 0) {
    shared_data_->SetLastError(kViECaptureDeviceUnknownError);
    return -1;
  }
  return 0;
}

int ViECaptureImpl::DeregisterObserver(const int capture_id) {
  ViEInputManagerScoped is(*(shared_data_->input_manager()));
  ViECapturer* vie_capture = is.Capture(capture_id);
  if (!vie_capture) {
    shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
    return -1;
  }
  if (!vie_capture->IsObserverRegistered()) {
    shared_data_->SetLastError(kViECaptureDeviceObserverNotRegistered);
    return -1;
  }

  if (vie_capture->DeRegisterObserver() != 0) {
    shared_data_->SetLastError(kViECaptureDeviceUnknownError);
    return -1;
  }
  return 0;
}

}  // namespace webrtc
