// Copyright 2020 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 <fuchsia/camera2/hal/cpp/fidl.h>
#include <fuchsia/hardware/camera/cpp/fidl.h>
#include <fuchsia/ui/policy/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/cpp/executor.h>
#include <lib/async/cpp/wait.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fdio.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/syslog/cpp/log_settings.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/trace-provider/provider.h>
#include <lib/zx/result.h>

#include <filesystem>
#include <string>

#include "src/camera/bin/device/device_impl.h"
#include "src/camera/bin/device/metrics_reporter.h"

namespace camera {

constexpr auto kCameraPath = "/dev/class/camera";

using DeviceHandle = fuchsia::hardware::camera::DeviceHandle;

static zx::result<DeviceHandle> GetCameraHandle() {
  for (auto const& dir_entry : std::filesystem::directory_iterator{kCameraPath}) {
    DeviceHandle camera;
    zx_status_t status =
        fdio_service_connect(dir_entry.path().c_str(), camera.NewRequest().TakeChannel().release());
    return zx::make_result(status, std::move(camera));
  }
  return zx::error(ZX_ERR_NOT_FOUND);
}

}  // namespace camera

int main(int argc, char* argv[]) {
  fuchsia_logging::SetLogSettings({.min_log_level = CAMERA_MIN_LOG_LEVEL},
                                  {"camera", "camera_device"});

  async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
  async::Executor executor(loop.dispatcher());
  trace::TraceProviderWithFdio trace_provider(loop.dispatcher());
  auto context = sys::ComponentContext::Create();

  std::string outgoing_service_name("fuchsia.camera3.Device");

  // Special hack to connect to controller. Works for one device, but not for multiple.
  // TODO(ernesthua) - Need to make this scalable to multiple devices. camera_device_watcher knows
  // about the specific device just found, so that information must be passed to camera_device
  // instead of hardcoding it here.
  fuchsia::camera2::hal::ControllerSyncPtr controller;
  {
    zx::result result = camera::GetCameraHandle();
    if (result.is_error()) {
      FX_PLOGS(INFO, result.status_value())
          << "Couldn't get camera from. This device will not be exposed to clients.";
      return EXIT_FAILURE;
    }
    camera::DeviceHandle& device_handle = result.value();
    fuchsia::hardware::camera::DeviceSyncPtr device;
    device.Bind(std::move(device_handle));

    auto status = device->GetChannel2(controller.NewRequest());
    if (status != ZX_OK) {
      FX_PLOGS(FATAL, status) << "Failed to request controller service.";
      return EXIT_FAILURE;
    }

    fuchsia::camera2::DeviceInfo device_info;
    status = controller->GetDeviceInfo(&device_info);
    if (status != ZX_OK) {
      FX_PLOGS(FATAL, status) << "Failed to probe for device info.";
      return EXIT_FAILURE;
    }
  }

  // Connect to required environment services.
  fuchsia::sysmem::AllocatorHandle allocator;
  auto status = context->svc()->Connect(allocator.NewRequest());
  if (status != ZX_OK) {
    FX_PLOGS(FATAL, status) << "Failed to request allocator service.";
    return EXIT_FAILURE;
  }

  fuchsia::ui::policy::DeviceListenerRegistryHandle registry;
  status = context->svc()->Connect(registry.NewRequest());
  if (status != ZX_OK) {
    FX_PLOGS(FATAL, status) << "Failed to request registry service.";
    return EXIT_FAILURE;
  }

  // Post a quit task in the event the device enters a bad state.
  zx::event event;
  FX_CHECK(zx::event::create(0, &event) == ZX_OK);
  async::Wait wait(event.get(), ZX_EVENT_SIGNALED, 0,
                   [&](async_dispatcher_t* dispatcher, async::Wait* wait, zx_status_t status,
                       const zx_packet_signal_t* signal) {
                     FX_LOGS(FATAL) << "Device signaled bad state.";
                     loop.Quit();
                   });
  ZX_ASSERT(wait.Begin(loop.dispatcher()) == ZX_OK);

  // Create our metrics reporter.
  camera::MetricsReporter::Initialize(*context, /* enable_cobalt = */ true);

  // Create the device and publish its service.
  auto result =
      camera::DeviceImpl::Create(loop.dispatcher(), executor, std::move(controller),
                                 std::move(allocator), std::move(registry), std::move(event));
  std::unique_ptr<camera::DeviceImpl> device;
  executor.schedule_task(
      result.then([&context, &device, &loop, &outgoing_service_name](
                      fpromise::result<std::unique_ptr<camera::DeviceImpl>, zx_status_t>& result) {
        if (result.is_error()) {
          FX_PLOGS(FATAL, result.error()) << "Failed to create device.";
          loop.Quit();
          return;
        }
        device = result.take_value();

        // TODO(https://fxbug.dev/42121063): publish discoverable service name once supported
        zx_status_t status =
            context->outgoing()->AddPublicService(device->GetHandler(), outgoing_service_name);
        if (status != ZX_OK) {
          FX_PLOGS(FATAL, status) << "Failed to publish service.";
          loop.Quit();
          return;
        }
        context->outgoing()->ServeFromStartupInfo();
      }));

  loop.Run();
  return EXIT_SUCCESS;
}
