// Copyright 2022 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 "parent-driver.h"

// [START bind_imports]
#include <bind/examples/gizmo/bind/cpp/bind.h>
#include <bind/examples/gizmo/cpp/bind.h>
#include <bind/fuchsia/device/fs/cpp/bind.h>
// [END bind_imports]

namespace parent_driver {

zx::result<> ParentDriver::Start() {
  node_.Bind(std::move(node()), dispatcher());
  gizmo_server_ = std::make_shared<GizmoServer>(&logger());

  // Add gizmo examples_gizmo::Service to outgoing.
  {
    component::ServiceInstanceHandler handler;
    examples_gizmo::Service::Handler service(&handler);
    auto result = service.add_testing(
        [this](fidl::ServerEnd<examples_gizmo::TestingProtocol> server_end) -> void {
          GizmoServer::BindDeviceClient(gizmo_server_, dispatcher(), std::move(server_end));
        });
    ZX_ASSERT(result.is_ok());

    result = context().outgoing()->AddService<examples_gizmo::Service>(std::move(handler));
    if (result.is_error()) {
      FDF_SLOG(ERROR, "Failed to add service", KV("status", result.status_string()));
      return result.take_error();
    }
  }

  auto result = AddChild();
  if (result.status_value() != ZX_OK) {
    return result;
  }

  return zx::ok();
}

zx::result<> ParentDriver::AddChild() {
  fidl::Arena arena;

  // Offer `examples.gizmo.Service` to the driver that binds to the node.
  auto offers = fidl::VectorView<fuchsia_component_decl::wire::Offer>(arena, 1);
  offers[0] = driver::MakeOffer<examples_gizmo::Service>(arena, component::kDefaultInstance);

  // Set the properties of the node that the child will bind to based on the child-driver.bind
  auto properties = fidl::VectorView<fuchsia_driver_framework::wire::NodeProperty>(arena, 6);
  // [START add_bind_properties]
  properties[0] =
      driver::MakeProperty(arena, 1 /* BIND_PROTOCOL */, bind_fuchsia_acpi::BIND_PROTOCOL_DEVICE);
  properties[1] = driver::MakeProperty(arena, bind_fuchsia_acpi::HID, "GOOG");
  properties[2] = driver::MakeProperty(arena, bind_examples_gizmo_bind::MODELNAME, "GIZMO3000");
  properties[3] = driver::MakeEnumProperty(arena, bind_examples_gizmo_bind::GIZMOTYPE,
                                           bind_examples_gizmo_bind::GIZMOTYPE_MEM_64K);
  // [END add_bind_properties]

  // We are not actually offering the Exporter protocol to the child, nor using it from the child.
  // This is just to demonstrate access to these values through the auto-generated bind library.
  // [START add_fidl_bind_properties]
  properties[4] = driver::MakeEnumProperty(arena, bind_fuchsia_device_fs::EXPORTER,
                                           bind_fuchsia_device_fs::EXPORTER_ZIRCONTRANSPORT);
  properties[5] = driver::MakeEnumProperty(arena, bind_examples_gizmo::TESTINGPROTOCOL,
                                           bind_examples_gizmo::TESTINGPROTOCOL_ZIRCONTRANSPORT);
  // [END add_fidl_bind_properties]

  auto args = fuchsia_driver_framework::wire::NodeAddArgs::Builder(arena)
                  .name(arena, "bindlib-child")
                  .offers(offers)
                  .properties(properties)
                  .Build();

  // Create endpoints of the `NodeController` for the node.
  auto endpoints = fidl::CreateEndpoints<fuchsia_driver_framework::NodeController>();
  if (endpoints.is_error()) {
    FDF_SLOG(ERROR, "Failed to create endpoint", KV("status", endpoints.status_string()));
    return zx::error(endpoints.status_value());
  }

  auto result = node_.sync()->AddChild(args, std::move(endpoints->server), {});
  if (!result.ok()) {
    FDF_SLOG(ERROR, "Failed to add child", KV("status", result.status_string()));
    return zx::error(result.status());
  }

  return zx::ok();
}

}  // namespace parent_driver

FUCHSIA_DRIVER_RECORD_CPP_V2(driver::Record<parent_driver::ParentDriver>);
