// 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 <fidl/fuchsia.device.fs/cpp/wire.h>
#include <fidl/fuchsia.driver.compat/cpp/wire.h>
#include <fidl/fuchsia.driver.framework/cpp/wire.h>
#include <fidl/fuchsia.hardware.demo/cpp/wire.h>
#include <lib/driver2/namespace.h>
#include <lib/driver2/record_cpp.h>
#include <lib/driver2/start_args.h>
#include <lib/driver2/structured_logger.h>
#include <lib/sys/component/llcpp/outgoing_directory.h>
#include <zircon/errors.h>

namespace fdf2 = fuchsia_driver_framework;
namespace fio = fuchsia_io;

namespace {

class DemoNumber : public fidl::WireServer<fuchsia_hardware_demo::Demo> {
 public:
  DemoNumber(async_dispatcher_t* dispatcher, fidl::WireSharedClient<fdf2::Node> node,
             driver::Namespace ns, component::OutgoingDirectory outgoing, driver::Logger logger)
      : dispatcher_(dispatcher),
        outgoing_(std::move(outgoing)),
        node_(std::move(node)),
        ns_(std::move(ns)),
        logger_(std::move(logger)) {}

  static constexpr const char* Name() { return "demo_number"; }

  static zx::status<std::unique_ptr<DemoNumber>> Start(fdf2::wire::DriverStartArgs& start_args,
                                                       fdf::UnownedDispatcher dispatcher,
                                                       fidl::WireSharedClient<fdf2::Node> node,
                                                       driver::Namespace ns,
                                                       driver::Logger logger) {
    auto outgoing = component::OutgoingDirectory::Create(dispatcher->async_dispatcher());
    auto driver =
        std::make_unique<DemoNumber>(dispatcher->async_dispatcher(), std::move(node), std::move(ns),
                                     std::move(outgoing), std::move(logger));

    auto result = driver->Run(std::move(start_args.outgoing_dir()));
    if (result.is_error()) {
      return result.take_error();
    }
    return zx::ok(std::move(driver));
  }

 private:
  zx::status<> Run(fidl::ServerEnd<fio::Directory> outgoing_dir) {
    // Connect to DevfsExporter.
    auto exporter = ns_.Connect<fuchsia_device_fs::Exporter>();
    if (exporter.status_value() != ZX_OK) {
      return exporter.take_error();
    }
    exporter_ = fidl::WireClient(std::move(*exporter), dispatcher_);

    // Connect to parent.
    auto parent = ns_.Connect<fuchsia_driver_compat::Device>(
        "/svc/fuchsia.driver.compat.Service/default/device");
    if (parent.status_value() != ZX_OK) {
      return parent.take_error();
    }

    auto result = fidl::WireCall(*parent)->GetTopologicalPath();
    if (!result.ok()) {
      return zx::error(result.status());
    }

    std::string path(result.value().path.data(), result.value().path.size());

    auto status = outgoing_.AddProtocol<fuchsia_hardware_demo::Demo>(this, Name());
    if (status.status_value() != ZX_OK) {
      return status;
    }

    path.append("/");
    path.append(Name());

    FDF_LOG(INFO, "Exporting device to: %s", path.data());

    // Serve a connection to outgoing.
    auto endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();
    if (endpoints.is_error()) {
      return endpoints.take_error();
    }
    {
      auto status = outgoing_.Serve(std::move(endpoints->server));
      if (status.is_error()) {
        return status.take_error();
      }
    }

    // Export our protocol.
    exporter_
        ->Export(std::move(endpoints->client),
                 fidl::StringView::FromExternal(std::string("svc/").append(Name())),
                 fidl::StringView::FromExternal(path), 0)
        .Then([this](fidl::WireUnownedResult<fuchsia_device_fs::Exporter::Export>& result) {
          if (!result.ok()) {
            FDF_LOG(ERROR, "Exporting failed with: %s", result.status_string());
          }
        });

    return outgoing_.Serve(std::move(outgoing_dir));
  }

  void GetNumber(GetNumberRequestView request, GetNumberCompleter::Sync& completer) override {
    completer.Reply(current_number);
    current_number += 1;
  }

  async_dispatcher_t* dispatcher_;
  component::OutgoingDirectory outgoing_;

  fidl::WireSharedClient<fdf2::Node> node_;

  driver::Namespace ns_;
  driver::Logger logger_;
  fidl::WireClient<fuchsia_device_fs::Exporter> exporter_;

  std::string parent_topo_path_;
  uint32_t current_number = 0;
};

}  // namespace

FUCHSIA_DRIVER_RECORD_CPP_V1(DemoNumber);
