// 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/tests/composite-driver-v1/composite_driver_v1.h"

#include <fidl/fuchsia.composite.test/cpp/wire.h>

#include <set>

#include "src/devices/tests/composite-driver-v1/composite_driver_v1-bind.h"

namespace composite_driver_v1 {

zx::status<uint32_t> DoFidlConnections(zx_device_t* dev, const char* fragment) {
  auto endpoints = fidl::CreateEndpoints<fuchsia_composite_test::Device>();
  zx_status_t status = device_connect_fragment_fidl_protocol(
      dev, fragment, "fuchsia.composite.test.Device", endpoints->server.TakeChannel().release());
  if (status != ZX_OK) {
    zxlogf(INFO, "Failed to connect: %s", zx_status_get_string(status));
    return zx::error(status);
  }
  auto result = fidl::WireCall(endpoints->client)->GetNumber();
  if (result.status() != ZX_OK) {
    zxlogf(ERROR, "Failed to call number: %s", result.lossy_description());
    return zx::error(result.status());
  }
  return zx::ok(result.value().number);
}

zx_status_t CompositeDriverV1::Bind(void* ctx, zx_device_t* dev) {
  uint32_t count = device_get_fragment_count(dev);
  if (count != 3) {
    zxlogf(ERROR, "Wrong fragment count: expected 3, got %d", count);
    return ZX_ERR_INTERNAL;
  }

  std::vector<composite_device_fragment_t> fragments(count);
  std::set<std::string> expected_fragments;
  expected_fragments.insert("a");
  expected_fragments.insert("b");
  expected_fragments.insert("c");

  size_t actual = 0;
  bool error = false;
  device_get_fragments(dev, fragments.data(), fragments.size(), &actual);
  for (auto& fragment : fragments) {
    if (expected_fragments.count(fragment.name) == 1) {
      expected_fragments.erase(fragment.name);
    } else {
      zxlogf(ERROR, "Found unexpected fragment: %s", fragment.name);
      error = true;
    }
  }
  if (!expected_fragments.empty()) {
    error = true;
    for (auto& fragment : expected_fragments) {
      zxlogf(ERROR, "Didn't find expected fragment: %s", fragment.data());
    }
  }
  if (error) {
    return ZX_ERR_INTERNAL;
  }

  auto result = DoFidlConnections(dev, "a");
  if (result.status_value() != ZX_OK) {
    return result.status_value();
  }
  if (*result != 1) {
    zxlogf(ERROR, "Result for a is not correct: expected 1: got %d", *result);
    return ZX_ERR_INTERNAL;
  }
  result = DoFidlConnections(dev, "b");
  if (result.status_value() != ZX_OK) {
    return result.status_value();
  }
  if (*result != 2) {
    zxlogf(ERROR, "Result for b is not correct: expected 2: got %d", *result);
    return ZX_ERR_INTERNAL;
  }

  uint32_t metadata = 0;
  zx_status_t status = device_get_metadata(dev, 1, &metadata, sizeof(metadata), &actual);
  if (status != ZX_OK) {
    zxlogf(ERROR, "Failed to get metadata 1: %s", zx_status_get_string(status));
    return ZX_ERR_INTERNAL;
  }
  if (metadata != 4) {
    zxlogf(ERROR, "Got wrong metadata: expected 4: got %d", metadata);
    return ZX_ERR_INTERNAL;
  }

  status = device_get_metadata(dev, 2, &metadata, sizeof(metadata), &actual);
  if (status != ZX_OK) {
    zxlogf(ERROR, "Failed to get metadata 2: %s", zx_status_get_string(status));
    return ZX_ERR_INTERNAL;
  }
  if (metadata != 5) {
    zxlogf(ERROR, "Got wrong metadata: expected 5: got %d", metadata);
    return ZX_ERR_INTERNAL;
  }

  auto device = std::make_unique<CompositeDriverV1>(dev);
  status = device->Bind();
  if (status != ZX_OK) {
    return status;
  }
  __UNUSED auto ptr = device.release();
  return ZX_OK;
}

zx_status_t CompositeDriverV1::Bind() {
  is_bound.Set(true);
  return DdkAdd(ddk::DeviceAddArgs("composite_child").set_inspect_vmo(inspect_.DuplicateVmo()));
}

void CompositeDriverV1::DdkInit(ddk::InitTxn txn) { txn.Reply(ZX_OK); }

void CompositeDriverV1::DdkRelease() { delete this; }

static zx_driver_ops_t composite_driver_v1_driver_ops = []() -> zx_driver_ops_t {
  zx_driver_ops_t ops = {};
  ops.version = DRIVER_OPS_VERSION;
  ops.bind = CompositeDriverV1::Bind;
  return ops;
}();

}  // namespace composite_driver_v1

ZIRCON_DRIVER(CompositeDriverV1, composite_driver_v1::composite_driver_v1_driver_ops, "zircon",
              "0.1");
