// Copyright 2018 The Fuchsia 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 <ddk/debug.h>
#include "src/lib/fxl/logging.h"

#include "garnet/drivers/usb_video/camera_control_impl.h"
#include "garnet/drivers/usb_video/usb-video-stream.h"

namespace camera {

void ControlImpl::OnFrameAvailable(
    const fuchsia::camera::FrameAvailableEvent& frame) {
  stream_->OnFrameAvailable(frame);
}

ControlImpl::ControlImpl(video::usb::UsbVideoStream* usb_video_stream,
                         fidl::InterfaceRequest<Control> control,
                         async_dispatcher_t* dispatcher,
                         fit::closure on_connection_closed)
    : binding_(this, std::move(control), dispatcher),
      usb_video_stream_(usb_video_stream) {
  binding_.set_error_handler(
      [occ = std::move(on_connection_closed)](zx_status_t status) { occ(); });
}

void ControlImpl::GetFormats(uint32_t index, GetFormatsCallback callback) {
  if (formats_->size() == 0) {
    zx_status_t status = usb_video_stream_->GetFormats(formats_);
    if (status != ZX_OK) {
      callback(std::move(formats_), formats_->size(), status);
      return;
    }
  }

  size_t min_index = std::max((size_t)0, std::min((size_t)index, formats_->size() - 1));
  size_t max_index =
      std::min(min_index + fuchsia::camera::MAX_FORMATS_PER_RESPONSE - 1,
               formats_->size() - 1);

  callback(std::vector<fuchsia::camera::VideoFormat>(
               &(*formats_)[min_index], &(*formats_)[max_index + 1]),
           formats_->size(), ZX_OK);
}

void ControlImpl::GetDeviceInfo(GetDeviceInfoCallback callback) {
  // This is just a conversion from the format internal to the device driver
  // to the FIDL DeviceInfo struct.
  const auto& usb_device_info = usb_video_stream_->GetDeviceInfo();
  fuchsia::camera::DeviceInfo camera_device_info;
  camera_device_info.vendor_name = usb_device_info.manufacturer;
  camera_device_info.vendor_id = usb_device_info.vendor_id;
  camera_device_info.product_name = usb_device_info.product_name;
  camera_device_info.product_id = usb_device_info.product_id;
  camera_device_info.serial_number = usb_device_info.serial_number;

  // TODO(CAM-11): add more capabilities based on usb description
  camera_device_info.output_capabilities =
      fuchsia::camera::CAMERA_OUTPUT_STREAM;
  camera_device_info.max_stream_count = 1;
  callback(std::move(camera_device_info));
}

void ControlImpl::CreateStream(
    fuchsia::sysmem::BufferCollectionInfo buffer_collection,
    fuchsia::camera::FrameRate frame_rate,
    fidl::InterfaceRequest<fuchsia::camera::Stream> stream,
    zx::eventpair stream_token) {
  zx_status_t status =
      usb_video_stream_->CreateStream(std::move(buffer_collection), frame_rate);

  if (status != ZX_OK) {
    zxlogf(ERROR, "Failed to set format. Closing channel.\n");
    binding_.Unbind();  // Close the channel on error.
    return;
  }

  stream_ = std::make_unique<StreamImpl>(*this, std::move(stream),
                                         std::move(stream_token));
}

void ControlImpl::StreamImpl::OnFrameAvailable(
    const fuchsia::camera::FrameAvailableEvent& frame) {
  binding_.events().OnFrameAvailable(frame);
}

void ControlImpl::StreamImpl::Start() {
  zx_status_t status = owner_.usb_video_stream_->StartStreaming();
  if (status != ZX_OK) {
    zxlogf(ERROR, "Failed to start. Closing channel.\n");
    binding_.Unbind();  // Close the channel on error.
  }
}

void ControlImpl::StreamImpl::Stop() {
  zx_status_t status = owner_.usb_video_stream_->StopStreaming();
  if (status != ZX_OK) {
    zxlogf(ERROR, "Failed to stop. Closing channel.\n");
    binding_.Unbind();  // Close the channel on error.
  }
}

void ControlImpl::StreamImpl::ReleaseFrame(uint32_t buffer_index) {
  zx_status_t status = owner_.usb_video_stream_->FrameRelease(buffer_index);
  if (status != ZX_OK) {
    zxlogf(ERROR, "Failed to release frame. Closing channel.\n");
    binding_.Unbind();  // Close the channel on error.
  }
}

void ControlImpl::ShutDownStream() {
  // This has the effect of cancelling the wait, deleting the
  // stream_token, and unbinding from the stream channel.
  stream_ = nullptr;
}

ControlImpl::StreamImpl::~StreamImpl() {
  // Doesn't matter what this returns:
  (void)owner_.usb_video_stream_->StopStreaming();
}

ControlImpl::StreamImpl::StreamImpl(
    ControlImpl& owner, fidl::InterfaceRequest<fuchsia::camera::Stream> stream,
    zx::eventpair stream_token)
    : owner_(owner),
      binding_(this, std::move(stream)),
      stream_token_(std::move(stream_token)),
      // If not triggered by the token being closed, this waiter will be
      // cancelled by the destruction of this class, so the "this" pointer will
      // be valid as long as the waiter is around.
      stream_token_waiter_(
          stream_token_.get(), ZX_EVENTPAIR_PEER_CLOSED, std::bind([this]() {
            zxlogf(
                INFO,
                "ControlImpl::StreamImpl::StreamImpl - "
                "ZX_EVENTPAIR_PEER_CLOSED received, shutting down stream.\n");
            // If the peer is closed, shut down the whole
            // stream.
            owner_.ShutDownStream();
            // We just deleted ourselves. Don't do anything
            // else.
          })) {
  zx_status_t status =
      stream_token_waiter_.Begin(async_get_default_dispatcher());
  // The waiter, dispatcher and token are known to be valid, so this should
  // never fail.
  FXL_CHECK(status == ZX_OK);
  binding_.set_error_handler([this](zx_status_t status) {
    owner_.usb_video_stream_->DeactivateVideoBuffer();
  });
}

}  // namespace camera
