// 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/bin/driver_manager/devfs_exporter.h"

#include "src/devices/lib/log/log.h"
#include "src/lib/storage/vfs/cpp/service.h"

namespace fdfs = fuchsia_device_fs;

namespace driver_manager {

zx::status<std::unique_ptr<ExportWatcher>> ExportWatcher::Create(
    async_dispatcher_t* dispatcher, Devnode* root,
    fidl::ClientEnd<fuchsia_io::Directory> service_dir, std::string_view service_path,
    std::string_view devfs_path, uint32_t protocol_id) {
  auto endpoints = fidl::CreateEndpoints<fuchsia_io::Node>();
  if (endpoints.is_error()) {
    return zx::error(endpoints.error_value());
  }

  auto response =
      fidl::WireCall(service_dir)
          ->Open(fuchsia_io::wire::OpenFlags::kRightReadable |
                     fuchsia_io::wire::OpenFlags::kRightWritable,
                 0, fidl::StringView::FromExternal(service_path), std::move(endpoints->server));
  if (!response.ok()) {
    return zx::error(response.error().status());
  }

  auto watcher = std::make_unique<ExportWatcher>();
  watcher->client_ = fidl::WireClient(std::move(endpoints->client), dispatcher, watcher.get());

  zx_status_t status = devfs_export(root, std::move(service_dir), service_path, devfs_path,
                                    protocol_id, watcher->devnodes_);
  if (status != ZX_OK) {
    return zx::error(status);
  }

  return zx::ok(std::move(watcher));
}

DevfsExporter::DevfsExporter(Devnode* root, async_dispatcher_t* dispatcher)
    : root_(root), dispatcher_(dispatcher) {}

zx::status<> DevfsExporter::PublishExporter(const fbl::RefPtr<fs::PseudoDir>& svc_dir) {
  const auto service = [this](fidl::ServerEnd<fdfs::Exporter> request) {
    fidl::BindServer(dispatcher_, std::move(request), this);
    return ZX_OK;
  };
  zx_status_t status = svc_dir->AddEntry(fidl::DiscoverableProtocolName<fdfs::Exporter>,
                                         fbl::MakeRefCounted<fs::Service>(service));
  if (status != ZX_OK) {
    LOGF(ERROR, "Failed to add directory entry '%s': %s",
         fidl::DiscoverableProtocolName<fdfs::Exporter>, zx_status_get_string(status));
  }
  return zx::make_status(status);
}

void DevfsExporter::Export(ExportRequestView request, ExportCompleter::Sync& completer) {
  auto result = ExportWatcher::Create(dispatcher_, root_, std::move(request->service_dir),
                                      request->service_path.get(), request->devfs_path.get(),
                                      request->protocol_id);
  if (result.is_error()) {
    LOGF(ERROR, "Failed to export service to devfs path \"%.*s\": %s",
         static_cast<int>(request->devfs_path.size()), request->devfs_path.data(),
         result.status_string());
    completer.ReplyError(result.error_value());
    return;
  }

  ExportWatcher* export_ptr = result.value().get();
  exports_.push_back(std::move(result.value()));

  // Set a callback so when the ExportWatcher sees its connection closed, it
  // will delete itself and its devnodes.
  export_ptr->set_on_close_callback([this, export_ptr]() {
    exports_.erase(std::remove_if(exports_.begin(), exports_.end(),
                                  [&](const auto& it) { return it.get() == export_ptr; }),
                   exports_.end());
  });

  completer.ReplySuccess();
}

}  // namespace driver_manager
