// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media_perception/video_capture_service_client_impl.h"

#include <utility>
#include <base/single_thread_task_runner.h>

#include "media_perception/device_management.pb.h"
#include "media_perception/proto_mojom_conversion.h"
#include "media_perception/serialized_proto.h"

namespace mri {

void VideoCaptureServiceClientImpl::SetMojoConnector(
    MojoConnector* mojo_connector) {
  mojo_connector_ = mojo_connector;
}

bool VideoCaptureServiceClientImpl::Connect() {
  if (mojo_connector_ == nullptr) {
    LOG(ERROR) << "Mojo connector is nullptr.";
    return false;
  }
  mojo_connector_->ConnectToVideoCaptureService();
  return true;
}

bool VideoCaptureServiceClientImpl::IsConnected() {
  if (mojo_connector_ == nullptr)
    return false;

  return mojo_connector_->IsConnectedToVideoCaptureService();
}

void VideoCaptureServiceClientImpl::GetDevices(
    const GetDevicesCallback& callback) {
  mojo_connector_->GetDevices(callback);
}

void VideoCaptureServiceClientImpl::OpenDevice(
    const std::string& device_id,
    bool force_reopen_with_settings,
    const SerializedVideoStreamParams& capture_format,
    const OpenDeviceCallback& callback) {
  VideoStreamParams format = Serialized<VideoStreamParams>(
      capture_format).Deserialize();

  std::lock_guard<std::mutex> lock(device_id_to_video_frame_handler_map_lock_);
  std::map<std::string, std::shared_ptr<VideoFrameHandlerImpl>>::iterator it =
      device_id_to_video_frame_handler_map_.find(device_id);
  if (it != device_id_to_video_frame_handler_map_.end() &&
      it->second->HasValidCaptureFormat()) {
    LOG(INFO) << "Device with " << device_id << " already open.";
    SerializedVideoStreamParams current_format =
        Serialized<VideoStreamParams>(
            it->second->GetCaptureFormat()).GetBytes();

    // Device already open with the same settings.
    if (it->second->CaptureFormatsMatch(format)) {
      callback(
          device_id,
          CreatePushSubscriptionResultCode::CREATED_WITH_REQUESTED_SETTINGS,
          current_format);
      return;
    }
    // Device already open but with different settings.
    callback(
        device_id,
        CreatePushSubscriptionResultCode::CREATED_WITH_DIFFERENT_SETTINGS,
        current_format);
    return;
  }

  std::shared_ptr<VideoFrameHandlerImpl> video_frame_handler_impl;
  if (it != device_id_to_video_frame_handler_map_.end()) {
    video_frame_handler_impl = it->second;
  } else {  // Create video_frame_handler if it doesn't exist.
    video_frame_handler_impl = std::make_shared<VideoFrameHandlerImpl>();
  }
  device_id_to_video_frame_handler_map_.insert(
      std::make_pair(device_id, video_frame_handler_impl));
  mojo_connector_->OpenDevice(
      device_id, force_reopen_with_settings, video_frame_handler_impl, format,
      std::bind(&VideoCaptureServiceClientImpl::OnOpenDeviceCallback,
                this, callback, std::placeholders::_1,
                std::placeholders::_2, std::placeholders::_3));
}

void VideoCaptureServiceClientImpl::OnOpenDeviceCallback(
      const OpenDeviceCallback& callback,
      std::string device_id,
      CreatePushSubscriptionResultCode code,
      SerializedVideoStreamParams params) {
  VideoStreamParams format = Serialized<VideoStreamParams>(
      params).Deserialize();
  {
    std::lock_guard<std::mutex> lock(device_id_to_video_frame_handler_map_lock_);
    std::map<std::string, std::shared_ptr<VideoFrameHandlerImpl>>::iterator it =
        device_id_to_video_frame_handler_map_.find(device_id);
    if (it != device_id_to_video_frame_handler_map_.end() &&
        code != CreatePushSubscriptionResultCode::FAILED) {
      it->second->SetCaptureFormat(format);
    }
  }
  callback(device_id, code, params);
}

bool VideoCaptureServiceClientImpl::IsVideoCaptureStartedForDevice(
    const std::string& device_id,
    SerializedVideoStreamParams* capture_format) {
  std::lock_guard<std::mutex> lock(device_id_to_video_frame_handler_map_lock_);
  std::map<std::string, std::shared_ptr<VideoFrameHandlerImpl>>::iterator it =
      device_id_to_video_frame_handler_map_.find(device_id);
  bool capture_started = it != device_id_to_video_frame_handler_map_.end() &&
      it->second->HasValidCaptureFormat();
  if (capture_started) {
    *capture_format = Serialized<VideoStreamParams>(
        it->second->GetCaptureFormat()).GetBytes();
  }
  return capture_started;
}

int VideoCaptureServiceClientImpl::AddFrameHandler(
    const std::string& device_id,
    FrameHandler handler) {
  std::lock_guard<std::mutex> lock(device_id_to_video_frame_handler_map_lock_);

  std::map<std::string, std::shared_ptr<VideoFrameHandlerImpl>>::iterator it =
      device_id_to_video_frame_handler_map_.find(device_id);
  if (it != device_id_to_video_frame_handler_map_.end()) {
    if (it->second->GetFrameHandlerCount() == 0) {
      // If no frame handlers exist for video_frame_handler, need to activate video
      // device.
      if (!mojo_connector_->ActivateDevice(device_id)) {
        // Failed to activate the device.
        return 0;
      }
    }
    return it->second->AddFrameHandler(std::move(handler));
  }
  return 0;
}

bool VideoCaptureServiceClientImpl::RemoveFrameHandler(
    const std::string& device_id, int frame_handler_id) {
  std::lock_guard<std::mutex> lock(device_id_to_video_frame_handler_map_lock_);
  std::map<std::string, std::shared_ptr<VideoFrameHandlerImpl>>::iterator it =
      device_id_to_video_frame_handler_map_.find(device_id);

  if (it == device_id_to_video_frame_handler_map_.end()) {
    // VideoFrameHandler does not exist. Ensure that the device is removed as well.
    mojo_connector_->StopVideoCapture(device_id);
    return false;
  }

  // VideoFrameHandler does exist.
  bool success = it->second->RemoveFrameHandler(frame_handler_id);
  if (it->second->GetFrameHandlerCount() == 0) {
    // Remove the video_frame_handler object.
    device_id_to_video_frame_handler_map_.erase(device_id);
    // Stop video capture on the device.
    mojo_connector_->StopVideoCapture(device_id);
  }
  return success;
}

void VideoCaptureServiceClientImpl::CreateVirtualDevice(
    const SerializedVideoDevice& video_device,
    const VirtualDeviceCallback& callback) {
  std::lock_guard<std::mutex> lock(device_id_to_producer_map_lock_);
  VideoDevice device = Serialized<VideoDevice>(video_device).Deserialize();

  auto producer_impl = std::make_shared<ProducerImpl>();
  mojo_connector_->CreateVirtualDevice(device, producer_impl, callback);

  device_id_to_producer_map_.insert(
      std::make_pair(device.id(), producer_impl));
}

void VideoCaptureServiceClientImpl::PushFrameToVirtualDevice(
    const std::string& device_id, uint64_t timestamp_in_microseconds,
    std::unique_ptr<const uint8_t[]> data, int data_size,
    RawPixelFormat pixel_format, int frame_width, int frame_height) {
  std::lock_guard<std::mutex> lock(device_id_to_producer_map_lock_);
  std::map<std::string, std::shared_ptr<ProducerImpl>>::iterator it =
      device_id_to_producer_map_.find(device_id);
  if (it == device_id_to_producer_map_.end()) {
    LOG(ERROR) << "Device id not found in producer map.";
    return;
  }
  mojo_connector_->PushFrameToVirtualDevice(
      it->second, base::TimeDelta::FromMicroseconds(timestamp_in_microseconds),
      std::move(data), data_size, static_cast<PixelFormat>(pixel_format),
      frame_width, frame_height);
}

void VideoCaptureServiceClientImpl::CloseVirtualDevice(
    const std::string& device_id) {
  std::lock_guard<std::mutex> lock(device_id_to_producer_map_lock_);
  // Erasing the producer object will close the virtual device.
  device_id_to_producer_map_.erase(device_id);
}

}  // namespace mri
