// Copyright 2017 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 "lib/svc/cpp/service_provider_bridge.h"

#include <fcntl.h>
#include <lib/async/default.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <zircon/device/vfs.h>

#include <utility>

#include <fs/service.h>
#include <fs/vfs_types.h>

namespace component {

ServiceProviderBridge::ServiceProviderBridge()
    : vfs_(async_get_default_dispatcher()), weak_factory_(this) {
  directory_ = fbl::AdoptRef(new ServiceProviderDir(weak_factory_.GetWeakPtr()));
}

ServiceProviderBridge::~ServiceProviderBridge() = default;

void ServiceProviderBridge::AddBinding(fidl::InterfaceRequest<ServiceProvider> request) {
  bindings_.AddBinding(this, std::move(request));
}

fidl::InterfaceHandle<fuchsia::sys::ServiceProvider> ServiceProviderBridge::AddBinding() {
  return bindings_.AddBinding(this);
}

void ServiceProviderBridge::AddServiceForName(ServiceConnector connector,
                                              const std::string& service_name) {
  name_to_service_connector_[service_name] = std::move(connector);
}

bool ServiceProviderBridge::ServeDirectory(zx::channel channel) {
  return vfs_.ServeDirectory(directory_, std::move(channel)) == ZX_OK;
}

zx::channel ServiceProviderBridge::OpenAsDirectory() {
  zx::channel h1, h2;
  if (zx::channel::create(0, &h1, &h2) < 0)
    return zx::channel();
  if (!ServeDirectory(std::move(h1)))
    return zx::channel();
  return h2;
}

int ServiceProviderBridge::OpenAsFileDescriptor() {
  zx::channel h1, h2;
  if (zx::channel::create(0, &h1, &h2) < 0)
    return -1;
  if (!ServeDirectory(std::move(h1)))
    return -1;
  int fd = -1;
  zx_status_t status = fdio_fd_create(h2.release(), &fd);
  if (status != ZX_OK)
    return -1;
  return fd;
}

void ServiceProviderBridge::ConnectToService(std::string service_name, zx::channel channel) {
  auto it = name_to_service_connector_.find(service_name);
  if (it != name_to_service_connector_.end())
    it->second(std::move(channel));
  else if (backend_)
    backend_->ConnectToService(service_name, std::move(channel));
  else if (backing_dir_)
    fdio_service_connect_at(backing_dir_.get(), service_name.c_str(), channel.release());
}

ServiceProviderBridge::ServiceProviderDir::ServiceProviderDir(
    fxl::WeakPtr<ServiceProviderBridge> bridge)
    : bridge_(std::move(bridge)) {}

ServiceProviderBridge::ServiceProviderDir::~ServiceProviderDir() = default;

fs::VnodeProtocolSet ServiceProviderBridge::ServiceProviderDir::GetProtocols() const {
  return fs::VnodeProtocol::kDirectory;
}

zx_status_t ServiceProviderBridge::ServiceProviderDir::Lookup(fbl::RefPtr<fs::Vnode>* out,
                                                              fbl::StringPiece name) {
  *out = fbl::AdoptRef(new fs::Service(
      [bridge = bridge_, name = std::string(name.data(), name.length())](zx::channel channel) {
        if (bridge) {
          bridge->ConnectToService(name, std::move(channel));
          return ZX_OK;
        }
        return ZX_ERR_NOT_FOUND;
      }));
  return ZX_OK;
}

zx_status_t ServiceProviderBridge::ServiceProviderDir::GetAttributes(fs::VnodeAttributes* attr) {
  *attr = fs::VnodeAttributes();
  attr->mode = V_TYPE_DIR | V_IRUSR;
  attr->link_count = 1;
  return ZX_OK;
}

zx_status_t ServiceProviderBridge::ServiceProviderDir::GetNodeInfoForProtocol(
    [[maybe_unused]] fs::VnodeProtocol protocol, [[maybe_unused]] fs::Rights rights,
    fs::VnodeRepresentation* representation) {
  *representation = fs::VnodeRepresentation::Directory();
  return ZX_OK;
}

}  // namespace component
