// 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 "src/camera/drivers/virtual_camera/virtual_camera_device.h"

#include "src/camera/drivers/virtual_camera/virtual_camera_control.h"
#include "src/lib/fxl/logging.h"

namespace virtual_camera {

std::unique_ptr<async::Loop> VirtualCameraDevice::fidl_dispatch_loop_ = nullptr;

#define DEV(c) static_cast<VirtualCameraDevice*>(c)
static zx_protocol_device_t virtual_camera_device_ops = {
    .version = DEVICE_OPS_VERSION,
    .unbind = [](void* ctx) { DEV(ctx)->Unbind(); },
    .release = [](void* ctx) { DEV(ctx)->Release(); },
    .message = [](void* ctx, fidl_msg_t* msg, fidl_txn_t* txn) -> zx_status_t {
      return DEV(ctx)->Message(msg, txn);
    },
};
#undef DEV

VirtualCameraDevice::VirtualCameraDevice() {
  if (fidl_dispatch_loop_ == nullptr) {
    fidl_dispatch_loop_ =
        std::make_unique<async::Loop>(&kAsyncLoopConfigNoAttachToThread);
    fidl_dispatch_loop_->StartThread();
  }
}

VirtualCameraDevice::~VirtualCameraDevice() {}

zx_status_t VirtualCameraDevice::Bind(zx_device_t* device) {
  device_add_args_t args = {};
  args.version = DEVICE_ADD_ARGS_VERSION;
  args.name = "virtual_camera";
  args.ctx = this;
  args.ops = &virtual_camera_device_ops;

  // Add the virtual_audio device node, under parent /dev/test.
  return device_add(device, &args, &dev_node_);
}

void VirtualCameraDevice::Unbind() {
  // Unpublish our device node.
  // DdkRemove();
}

void VirtualCameraDevice::Release() { delete this; }

zx_status_t VirtualCameraDevice::Message(fidl_msg_t* msg, fidl_txn_t* txn) {
  return fuchsia_hardware_camera_Device_dispatch(this, txn, msg,
                                                 &CAMERA_FIDL_THUNKS);
}

zx_status_t VirtualCameraDevice::GetChannel(zx_handle_t handle) {
  if (handle == ZX_HANDLE_INVALID) {
    return ZX_ERR_INVALID_ARGS;
  }

  // CameraStream FIDL interface
  static std::unique_ptr<VirtualCameraControlImpl>
      virtual_camera_camera_control_server_ = nullptr;

  if (virtual_camera_camera_control_server_ != nullptr) {
    FXL_LOG(ERROR) << "Camera Control already running";
    // TODO(CAM-XXX): support multiple concurrent clients.
    return ZX_ERR_INTERNAL;
  }

  zx::channel channel(handle);
  fidl::InterfaceRequest<fuchsia::camera::Control> control_interface(
      std::move(channel));

  if (control_interface.is_valid()) {
    virtual_camera_camera_control_server_ =
        std::make_unique<VirtualCameraControlImpl>(
            std::move(control_interface), fidl_dispatch_loop_->dispatcher(),
            [] { virtual_camera_camera_control_server_.reset(); });

    return ZX_OK;
  } else {
    return ZX_ERR_INTERNAL;
  }
}

const fuchsia_hardware_camera_Device_ops_t
    VirtualCameraDevice::CAMERA_FIDL_THUNKS{
        .GetChannel = [](void* ctx, zx_handle_t handle) -> zx_status_t {
          return reinterpret_cast<VirtualCameraDevice*>(ctx)->GetChannel(
              handle);
        },
    };

}  // namespace virtual_camera
