// Copyright 2019 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 <fidl/fuchsia.inspect/cpp/fidl.h>
#include <fidl/fuchsia.inspect/cpp/wire.h>
#include <fidl/fuchsia.kernel/cpp/wire.h>
#include <lib/component/incoming/cpp/protocol.h>
#include <lib/inspect/component/cpp/service.h>
#include <lib/kcounter/provider.h>
#include <lib/zx/channel.h>
#include <string.h>
#include <zircon/status.h>

#include "kcounter.h"

namespace {

/// Counter exposes kernel counter data in two ways:
///   fuchsia.kernel.Counter:
///     This protocol allows direct access to the Inspect VMO managed in the kernel
///
///   fuchsia.inspect.Tree:
///     This protocol is the standard Inspect tree server. It is how the kernel counter data
///     is exposed to tools such as `ffx inspect`.
class Counter : public fidl::WireServer<fuchsia_kernel::Counter>,
                public fidl::WireServer<fuchsia_inspect::Tree> {
 public:
  Counter(async_dispatcher_t* dispatcher, kcounter::VmoToInspectMapper mapper)
      : dispatcher_(dispatcher), mapper_(std::move(mapper)) {}

 private:
  void GetInspectVmo(GetInspectVmoCompleter::Sync& completer) override {
    fuchsia_mem::wire::Buffer buffer;
    if (zx_status_t status = mapper_.GetInspectVMO(&buffer.vmo); status != ZX_OK) {
      return completer.Reply(status, {});
    }
    if (zx_status_t status = buffer.vmo.get_size(&buffer.size); status != ZX_OK) {
      return completer.Reply(status, {});
    }
    completer.Reply(ZX_OK, std::move(buffer));
  }

  void UpdateInspectVmo(UpdateInspectVmoCompleter::Sync& completer) override {
    completer.Reply(mapper_.UpdateInspectVMO());
  }

  /// Get the VMO handle for the Inspector handled by this server.
  /// `UpdateInspectVMO` is executed on each call.
  void GetContent(GetContentCompleter::Sync& completer) override {
    mapper_.UpdateInspectVMO();

    fidl::Arena arena;
    auto content_builder = fuchsia_inspect::wire::TreeContent::Builder(arena);
    fuchsia_mem::wire::Buffer buffer;

    // send live VMO as the only writes that happen to this Inspector happen in `UpdateInspectVMO`
    mapper_.GetInspectVMO(&buffer.vmo);

    content_builder.buffer(std::move(buffer));
    completer.Reply(content_builder.Build());
  }

  /// Not implemented. Will never be executed.
  void OpenChild(OpenChildRequestView request, OpenChildCompleter::Sync& completer) override {
    // This is intentionally left blank as `Counter::ListChildNames` returns a server
    // handle with an empty name list. That precludes this function ever being executed.
    //
    // If lazy nodes are ever added to the wrapped Inspector, this and `ListChildNames` will either
    // need a full implementation, or the method for exposing the Inspector will need to change.
  }

  /// Returns a handle to a server that will always return 0 names.
  void ListChildNames(ListChildNamesRequestView request,
                      ListChildNamesCompleter::Sync& completer) override {
    // Always return 0 names
    inspect::TreeNameIterator::StartSelfManagedServer(
        dispatcher_, std::move(request->tree_iterator), std::vector<std::string>{});
  }

  async_dispatcher_t* dispatcher_;
  kcounter::VmoToInspectMapper mapper_;
};

zx_status_t Connect(void* ctx, async_dispatcher_t* dispatcher, const char* service_name,
                    zx_handle_t request) {
  zx::channel channel{request};
  if (fidl::DiscoverableProtocolName<fuchsia_kernel::Counter> == service_name) {
    fidl::BindServer(dispatcher, fidl::ServerEnd<fuchsia_kernel::Counter>{std::move(channel)},
                     static_cast<Counter*>(ctx));
    return ZX_OK;
  }

  return ZX_ERR_NOT_SUPPORTED;
}

zx_status_t Init(void** ctx) {
  auto* dispatcher = static_cast<async_dispatcher_t*>(*ctx);

  auto* counter = new Counter(dispatcher, kcounter::VmoToInspectMapper{});

  auto endpoints = fidl::CreateEndpoints<fuchsia_inspect::Tree>();
  fidl::BindServer(dispatcher, std::move(endpoints->server), counter);

  auto inspect_sink_client = component::Connect<fuchsia_inspect::InspectSink>().value();
  fidl::Client client(std::move(inspect_sink_client), dispatcher);
  auto result = client->Publish({{.tree = std::move(endpoints->client)}});
  ZX_ASSERT(result.is_ok());

  *ctx = counter;
  return ZX_OK;
}

void Release(void* ctx) { delete static_cast<Counter*>(ctx); }

constexpr const char* kKcounterServices[] = {
    fidl::DiscoverableProtocolName<fuchsia_kernel::Counter>,
    nullptr,
};

constexpr zx_service_ops_t kKcounterOps = {
    .init = Init,
    .connect = Connect,
    .release = Release,
};

constexpr zx_service_provider_t kcounter_service_provider = {
    .version = SERVICE_PROVIDER_VERSION,
    .services = kKcounterServices,
    .ops = &kKcounterOps,
};

}  // namespace

const zx_service_provider_t* kcounter_get_service_provider() { return &kcounter_service_provider; }
