// 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 "i2c_controller.h"

// [START bind_imports]
#include <bind/fuchsia/hardware/i2c/cpp/bind.h>
// [END bind_imports]

namespace i2c_temperature {

zx::result<> I2cTemperatureController::Start() {
  node_.Bind(std::move(node()), dispatcher());
  i2c_server_ = std::make_shared<I2cDeviceServer>(&logger());

  // Serve the fuchsia.hardware.i2c/Device protocol to clients through the
  // fuchsia.hardware.i2c/Service wrapper.
  fuchsia_hardware_i2c::Service::InstanceHandler handler({
    .device = [this](fidl::ServerEnd<fuchsia_hardware_i2c::Device> request) -> void {
        I2cDeviceServer::BindDeviceClient(i2c_server_, dispatcher(), std::move(request));
      }
  });
  auto result = context().outgoing()->AddService<fuchsia_hardware_i2c::Service>(std::move(handler));
  if (result.is_error()) {
    FDF_SLOG(ERROR, "Failed to add service", KV("status", result.status_string()));
    return result.take_error();
  }

  // Publish `fuchsia.driver.compat.Service` to the outgoing directory.
  child_ = compat::DeviceServer(std::string(name()), 0, std::string(name()));
  auto status = child_->Serve(dispatcher(), context().outgoing().get());
  if (status != ZX_OK) {
    FDF_SLOG(ERROR, "Failed to serve compat device server.",
             KV("status", zx_status_get_string(status)));
    return zx::error(status);
  }

  // Create a child node and offer capabilities to bound drivers.
  result = AddChild();
  if (!result.is_ok()) {
    FDF_SLOG(ERROR, "Failed to create child node.", KV("status", result.status_string()));

    return result.take_error();
  }

  return zx::ok();
}

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

  // Offer `fuchsia.driver.compat.Service` to drivers that bind to the node.
  auto offers = child_->CreateOffers(arena);
  // [START add_child_offer]
  // Offer `fuchsia.hardware.i2c.Device` to drivers that bind to the node.
  auto service_offer =
      driver::MakeOffer<fuchsia_hardware_i2c::Service>(arena, component::kDefaultInstance);
  // [END add_child_offer]
  offers.push_back(service_offer);

  // [START add_child_properties]
  // Set the properties of the node for drivers to target.
  auto properties = fidl::VectorView<fuchsia_driver_framework::wire::NodeProperty>(arena, 2);
  properties[0] = driver::MakeProperty(arena, bind_fuchsia_hardware_i2c::SERVICE,
                                       bind_fuchsia_hardware_i2c::SERVICE_ZIRCONTRANSPORT);
  properties[1] = driver::MakeProperty(arena, 0x0A02 /* BIND_I2C_ADDRESS */, 0xff);
  // [END add_child_properties]

  // [START add_child_node]
  auto args = fuchsia_driver_framework::wire::NodeAddArgs::Builder(arena)
                  .name(arena, "i2c-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());
  }

  controller_.Bind(std::move(endpoints->client), dispatcher());
  // [END add_child_node]

  return zx::ok();
}

}  // namespace i2c_temperature

FUCHSIA_DRIVER_RECORD_CPP_V2(driver::Record<i2c_temperature::I2cTemperatureController>);
