// 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/graphics/display/lib/framebuffer-display/framebuffer-display-driver.h"

#include <fidl/fuchsia.hardware.display.engine/cpp/fidl.h>
#include <fidl/fuchsia.hardware.sysmem/cpp/wire.h>
#include <fidl/fuchsia.sysmem2/cpp/wire.h>
#include <lib/driver/component/cpp/node_add_args.h>
#include <lib/driver/logging/cpp/logger.h>
#include <lib/driver/mmio/cpp/mmio-buffer.h>
#include <lib/fdf/cpp/dispatcher.h>

#include <memory>

#include <bind/fuchsia/cpp/bind.h>
#include <bind/fuchsia/display/cpp/bind.h>
#include <fbl/alloc_checker.h>

#include "src/graphics/display/lib/api-protocols/cpp/display-engine-events-fidl.h"
#include "src/graphics/display/lib/api-protocols/cpp/display-engine-fidl-adapter.h"
#include "src/graphics/display/lib/framebuffer-display/framebuffer-display.h"

namespace framebuffer_display {

FramebufferDisplayDriver::FramebufferDisplayDriver(
    std::string_view device_name, fdf::DriverStartArgs start_args,
    fdf::UnownedSynchronizedDispatcher driver_dispatcher)
    : fdf::DriverBase(device_name, std::move(start_args), std::move(driver_dispatcher)) {}

FramebufferDisplayDriver::~FramebufferDisplayDriver() = default;

zx::result<> FramebufferDisplayDriver::Start() {
  zx::result<> configure_hardware_result = ConfigureHardware();
  if (configure_hardware_result.is_error()) {
    fdf::error("Failed to configure hardware: {}", configure_hardware_result);
    return configure_hardware_result.take_error();
  }

  zx::result<std::unique_ptr<FramebufferDisplay>> framebuffer_display_result =
      CreateAndInitializeFramebufferDisplay();
  if (framebuffer_display_result.is_error()) {
    fdf::error("Failed to create and initialize FramebufferDisplay: {}",
               framebuffer_display_result);
    return framebuffer_display_result.take_error();
  }
  framebuffer_display_ = std::move(framebuffer_display_result).value();

  zx::result<> add_fidl_service_node_result = InitializeFidlServiceNode();
  if (add_fidl_service_node_result.is_error()) {
    fdf::error("Failed to add FIDL service node: {}", add_fidl_service_node_result);
    return add_fidl_service_node_result.take_error();
  }

  return zx::ok();
}

void FramebufferDisplayDriver::Stop() {}

zx::result<std::unique_ptr<FramebufferDisplay>>
FramebufferDisplayDriver::CreateAndInitializeFramebufferDisplay() {
  fbl::AllocChecker alloc_checker;
  engine_events_ = fbl::make_unique_checked<display::DisplayEngineEventsFidl>(&alloc_checker);
  if (!alloc_checker.check()) {
    fdf::error("Failed to allocate memory for DisplayEngineEventsFidl");
    return zx::error(ZX_ERR_NO_MEMORY);
  }

  zx::result<fdf::MmioBuffer> frame_buffer_mmio_result = GetFrameBufferMmioBuffer();
  if (frame_buffer_mmio_result.is_error()) {
    fdf::error("Failed to get frame buffer mmio buffer: {}", frame_buffer_mmio_result);
    return frame_buffer_mmio_result.take_error();
  }
  fdf::MmioBuffer frame_buffer_mmio = std::move(frame_buffer_mmio_result).value();

  zx::result<DisplayProperties> display_properties_result = GetDisplayProperties();
  if (display_properties_result.is_error()) {
    fdf::error("Failed to get display properties: {}", display_properties_result);
    return display_properties_result.take_error();
  }
  DisplayProperties display_properties = std::move(display_properties_result).value();

  zx::result<fidl::ClientEnd<fuchsia_hardware_sysmem::Sysmem>> sysmem_hardware_client_result =
      incoming()->Connect<fuchsia_hardware_sysmem::Sysmem>();
  if (sysmem_hardware_client_result.is_error()) {
    fdf::error("Failed to get hardware sysmem protocol: {}", sysmem_hardware_client_result);
    return sysmem_hardware_client_result.take_error();
  }
  fidl::WireSyncClient<fuchsia_hardware_sysmem::Sysmem> sysmem_hardware_client(
      std::move(sysmem_hardware_client_result).value());

  zx::result<fidl::ClientEnd<fuchsia_sysmem2::Allocator>> sysmem_client_result =
      incoming()->Connect<fuchsia_sysmem2::Allocator>();
  if (sysmem_client_result.is_error()) {
    fdf::error("Failed to get fuchsia.sysmem2.Allocator protocol: {}", sysmem_client_result);
    return sysmem_client_result.take_error();
  }
  fidl::WireSyncClient<fuchsia_sysmem2::Allocator> sysmem_client(
      std::move(sysmem_client_result).value());

  zx::result<fdf::SynchronizedDispatcher> create_dispatcher_result =
      fdf::SynchronizedDispatcher::Create(fdf::SynchronizedDispatcher::Options::kAllowSyncCalls,
                                          "framebuffer-display-dispatcher",
                                          [](fdf_dispatcher_t*) {});
  if (create_dispatcher_result.is_error()) {
    fdf::error("Failed to create framebuffer display dispatcher: {}", create_dispatcher_result);
    return create_dispatcher_result.take_error();
  }
  framebuffer_display_dispatcher_ = std::move(create_dispatcher_result).value();

  auto framebuffer_display = fbl::make_unique_checked<FramebufferDisplay>(
      &alloc_checker, engine_events_.get(), std::move(sysmem_client),
      std::move(sysmem_hardware_client), std::move(frame_buffer_mmio),
      std::move(display_properties), framebuffer_display_dispatcher_.async_dispatcher());
  if (!alloc_checker.check()) {
    fdf::error("Failed to allocate memory for FramebufferDisplay");
    return zx::error(ZX_ERR_NO_MEMORY);
  }

  engine_fidl_adapter_ = fbl::make_unique_checked<display::DisplayEngineFidlAdapter>(
      &alloc_checker, framebuffer_display.get(), engine_events_.get());
  if (!alloc_checker.check()) {
    fdf::error("Failed to allocate memory for DisplayEngineFidlAdapter");
    return zx::error(ZX_ERR_NO_MEMORY);
  }

  zx::result<> framebuffer_display_initialize_result = framebuffer_display->Initialize();
  if (framebuffer_display_initialize_result.is_error()) {
    fdf::error("Failed to initialize FramebufferDisplay: {}",
               framebuffer_display_initialize_result);
    return framebuffer_display_initialize_result.take_error();
  }

  return zx::ok(std::move(framebuffer_display));
}

zx::result<> FramebufferDisplayDriver::InitializeFidlServiceNode() {
  ZX_DEBUG_ASSERT(framebuffer_display_ != nullptr);
  ZX_DEBUG_ASSERT(engine_fidl_adapter_ != nullptr);

  // Serve `fuchsia.hardware.display.engine/Service` at the outgoing directory.
  fuchsia_hardware_display_engine::Service::InstanceHandler service_handler(
      {.engine = engine_fidl_adapter_->CreateHandler(*(driver_dispatcher()->get()))});
  zx::result<> add_service_result =
      outgoing()->AddService<fuchsia_hardware_display_engine::Service>(std::move(service_handler));
  if (add_service_result.is_error()) {
    fdf::error("Failed to add service: {}", add_service_result);
    return add_service_result.take_error();
  }

  const fuchsia_driver_framework::NodeProperty node_properties[] = {
      fdf::MakeProperty(bind_fuchsia::PROTOCOL, bind_fuchsia_display::BIND_PROTOCOL_ENGINE),
  };
  const std::vector<fuchsia_driver_framework::Offer> node_offers = {
      fdf::MakeOffer2<fuchsia_hardware_display_engine::Service>(),
  };

  zx::result<fidl::ClientEnd<fuchsia_driver_framework::NodeController>>
      node_controller_client_result = AddChild(name(), node_properties, node_offers);
  if (node_controller_client_result.is_error()) {
    fdf::error("Failed to add child node: {}", node_controller_client_result);
    return node_controller_client_result.take_error();
  }
  node_controller_ = fidl::WireSyncClient(std::move(node_controller_client_result).value());

  return zx::ok();
}

}  // namespace framebuffer_display
