// 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>();

  // Add gizmo examples_gizmo::Service to outgoing.
  {
    examples_gizmo::Service::InstanceHandler handler(
        {.testing = [this](fidl::ServerEnd<examples_gizmo::TestingProtocol> server_end) -> void {
          GizmoServer::BindDeviceClient(gizmo_server_, dispatcher(), std::move(server_end));
        }});

    auto result = 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] = fdf::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] =
      fdf::MakeProperty(arena, 1 /* BIND_PROTOCOL */, bind_fuchsia_acpi::BIND_PROTOCOL_DEVICE);
  properties[1] = fdf::MakeProperty(arena, bind_fuchsia_acpi::HID, "GOOG");
  properties[2] = fdf::MakeProperty(arena, bind_examples_gizmo_bind::MODELNAME, "GIZMO3000");
  properties[3] = fdf::MakeProperty(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] = fdf::MakeProperty(arena, bind_fuchsia_device_fs::EXPORTER,
                                    bind_fuchsia_device_fs::EXPORTER_ZIRCONTRANSPORT);
  properties[5] = fdf::MakeProperty(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(fdf::Record<parent_driver::ParentDriver>);
