// Copyright 2019 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/camera_manager2/camera_manager_app.h"

#include <fcntl.h>
#include <fuchsia/hardware/camera/c/fidl.h>
#include <lib/fdio/directory.h>

#include <string>

#include <ddk/debug.h>
#include <ddk/driver.h>
#include <fbl/auto_call.h>
#include <fbl/function.h>

#include "src/lib/syslog/cpp/logger.h"

namespace camera {

std::unique_ptr<CameraManagerApp> CameraManagerApp::Create(
    std::unique_ptr<sys::ComponentContext> context) {
  FX_LOGS(INFO) << "Starting";

  auto camera_manager = std::make_unique<CameraManagerApp>(std::move(context));
  zx_status_t status =
      camera_manager->context_->svc()->Connect(camera_manager->sysmem_allocator_.NewRequest());
  if (status != ZX_OK) {
    FX_PLOGS(ERROR, status) << "Failed to connect to sysmem service";
    return nullptr;
  }

  // Begin monitoring for plug/unplug events for pluggable cameras.
  status = camera_manager->plug_detector_.Start(
      fbl::BindMember(camera_manager.get(), &CameraManagerApp::OnDeviceFound));
  if (status != ZX_OK) {
    FX_PLOGS(ERROR, status) << "Failed to start plug_detector";
    return nullptr;
  }

  camera_manager->context_->outgoing()->AddPublicService<fuchsia::camera2::Manager>(
      camera_manager->bindings_.GetHandler(camera_manager.get()));
  return camera_manager;
}

// The dispatcher loop should be shut down when this destructor is called.
// No further messages should be handled after this destructor is called.
CameraManagerApp::~CameraManagerApp() {
  // Stop monitoring plug/unplug events.  We are shutting down and
  // no longer care about devices coming and going.
  plug_detector_.Stop();
}

void CameraManagerApp::OnDeviceFound(
    fidl::InterfaceHandle<fuchsia::camera2::hal::Controller> controller) {
  auto device = VideoDeviceClient::Create(std::move(controller));
  if (!device) {
    FX_LOGS(ERROR) << "Failed to create device";
    return;
  }
  // The device is fully set up at this point. The camera manager now needs to
  // assign a camera_id.
  // TODO(41683): If a device's info marks it as a previously known device,
  // it should be merged with that device instance.  That will allow the device
  // to maintain its id, mute status, and any other properties that must be retained
  // across boot.

  device->set_id(device_id_counter_++);
  devices_.push_back(std::move(device));
}

VideoDeviceClient *CameraManagerApp::GetActiveDevice(int32_t camera_id) {
  for (auto &device : devices_) {
    if (device->id() == camera_id) {
      return device.get();
    }
  }
  return nullptr;
}

// Currently, this function handles all the connections itself, and only
// connects to the first stream and format of the device.
void CameraManagerApp::ConnectToStream(
    int32_t camera_id, fuchsia::camera2::StreamConstraints constraints,
    fidl::InterfaceHandle<fuchsia::sysmem::BufferCollectionToken> token,
    fidl::InterfaceRequest<fuchsia::camera2::Stream> client_request,
    fuchsia::camera2::Manager::ConnectToStreamCallback callback) {
  auto cleanup = fbl::MakeAutoCall([&callback]() { callback({}); });

  // 1: Check that the camera exists:
  auto device = GetActiveDevice(camera_id);
  if (!device) {
    return;
  }

  uint32_t config_index = 0;
  uint32_t stream_type = 0;
  uint32_t image_format_index = constraints.has_format_index() ? constraints.format_index() : 0;

  // 2: Check constraints against the configs that the device offers.  If incompatible, fail.
  // 3: Pick a config, stream and image_format_index
  zx_status_t status = device->MatchConstraints(constraints, &config_index, &stream_type);
  if (status != ZX_OK) {
    FX_PLOGS(ERROR, status) << "Failed to match constraints";
    return;
  }

  FX_LOGS(INFO) << "Picked config " << config_index << " stream index: " << stream_type
                << " format index: " << image_format_index;
  // Get configs from the device:
  auto &out_configs = device->configs();
  ZX_ASSERT(out_configs.size() > config_index);
  ZX_ASSERT(out_configs[config_index].stream_configs.size() > stream_type);
  auto &stream_config = out_configs[config_index].stream_configs[stream_type];

  // 4: Now check if the stream is currently being used.  If it is, we could:
  //     - A) Close the other stream
  //     - B) Have two clients of one stream
  //     - C) Choose another compatible stream
  //     - D) Refuse this request.
  // For now, we will do:
  //       E) Don't even check
  // TODO(36260): Check if other streams are active, and apply some policy.

  // 5: Allocate the buffer collection.  The constraints from the device must be applied, as well as
  // constraints for all the image formats being offered.  These should be checked at some point by
  // the camera manager.
  fidl::InterfaceHandle<fuchsia::sysmem::BufferCollection> sysmem_collection;
  status =
      sysmem_allocator_->BindSharedCollection(std::move(token), sysmem_collection.NewRequest());
  if (status != ZX_OK) {
    FX_PLOGS(ERROR, status) << "BindSharedCollection failed";
    return;
  }

  // Now connect the client directly to the device
  status = device->CreateStream(config_index, stream_type, image_format_index,
                                std::move(sysmem_collection), std::move(client_request));
  if (status != ZX_OK) {
    FX_PLOGS(ERROR, status) << "CreateStream failed";
    return;
  }

  // Return the image format that was selected.
  callback(stream_config.image_formats[image_format_index]);
  cleanup.cancel();
}

}  // namespace camera
