// Copyright 2021 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/devices/lib/acpi/client.h"

#include <fidl/fuchsia.hardware.acpi/cpp/wire.h>
#include <lib/ddk/debug.h>
#include <lib/ddk/device.h>
#include <lib/ddk/driver.h>
#include <zircon/types.h>

#include "src/devices/lib/acpi/object.h"
#include "util.h"

namespace acpi {
zx::status<fidl::ClientEnd<fuchsia_hardware_acpi::Device>> Client::Connect(zx_device_t* parent) {
  auto endpoints = fidl::CreateEndpoints<fuchsia_hardware_acpi::Device>();
  if (endpoints.is_error()) {
    return endpoints.take_error();
  }
  zx_status_t result;
  if (device_get_fragment_count(parent) == 0) {
    result = device_connect_fidl_protocol(
        parent, fidl::DiscoverableProtocolName<fuchsia_hardware_acpi::Device>,
        endpoints->server.TakeChannel().release());
  } else {
    result = device_connect_fragment_fidl_protocol(
        parent, "acpi", fidl::DiscoverableProtocolName<fuchsia_hardware_acpi::Device>,
        endpoints->server.TakeChannel().release());
  }
  if (result != ZX_OK) {
    return zx::error(result);
  }

  return zx::ok(std::move(endpoints->client));
}

zx::status<Client> Client::Create(zx_device_t* parent) {
  auto end = Connect(parent);
  if (end.is_error()) {
    return end.take_error();
  }
  fidl::WireSyncClient<fuchsia_hardware_acpi::Device> wire_client(std::move(end.value()));

  return zx::ok(Client(std::move(wire_client)));
}

Client Client::Create(fidl::WireSyncClient<fuchsia_hardware_acpi::Device> client) {
  return Client(std::move(client));
}

zx::status<Object> Client::CallDsm(Uuid uuid, uint64_t revision, uint64_t func_index,
                                   std::optional<fuchsia_hardware_acpi::wire::Object> params) {
  std::array<fuchsia_hardware_acpi::wire::Object, 4> args;
  auto uuid_buf = fidl::VectorView<uint8_t>::FromExternal(uuid.bytes, kUuidBytes);
  args[0] = fuchsia_hardware_acpi::wire::Object::WithBufferVal(
      fidl::ObjectView<fidl::VectorView<uint8_t>>::FromExternal(&uuid_buf));
  args[1] = fuchsia_hardware_acpi::wire::Object::WithIntegerVal(
      fidl::ObjectView<uint64_t>::FromExternal(&revision));
  args[2] = fuchsia_hardware_acpi::wire::Object::WithIntegerVal(
      fidl::ObjectView<uint64_t>::FromExternal(&func_index));

  int argc = 3;
  if (params != std::nullopt) {
    args[3] = params.value();
    argc++;
  }

  auto result = client_->EvaluateObject(
      "_DSM", fuchsia_hardware_acpi::wire::EvaluateObjectMode::kPlainObject,
      fidl::VectorView<fuchsia_hardware_acpi::wire::Object>::FromExternal(args.data(), argc));
  if (!result.ok()) {
    return zx::error(result.status());
  }

  if (result->is_error()) {
    return zx::ok(Object(result->error_value()));
  }

  if (!result->value()->result.is_object()) {
    // We called EvaluateObject with mode == PlainObject, so don't expect anything else back.
    return zx::error(ZX_ERR_INTERNAL);
  }

  return zx::ok(Object(result->value()->result.object()));
}

}  // namespace acpi
