// Copyright 2018 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/dir.h>
#include <lib/vfs/cpp/pseudo_dir.h>
#include <lib/vfs/cpp/remote_dir.h>
#include <lib/vfs/cpp/service.h>
#include <zircon/assert.h>
#include <zircon/errors.h>
#include <zircon/types.h>

#include <algorithm>
#include <memory>

namespace {

constexpr char kPathDelimiter = '/';
constexpr size_t kPathDelimiterSize = 1;

// Adds a new empty directory |name| to |dir| and sets |out| to new directory.
zx_status_t AddNewEmptyDirectory(vfs::PseudoDir* dir, std::string name, vfs::PseudoDir** out) {
  auto subdir = std::make_unique<vfs::PseudoDir>();
  auto ptr = subdir.get();
  zx_status_t status = dir->AddEntry(std::move(name), std::move(subdir));
  if (status == ZX_OK) {
    *out = ptr;
  }
  return status;
}

// Disallow empty paths and paths like `.`, `..`, and so on.
bool IsPathValid(const std::string& path) {
  return !path.empty() && !std::all_of(path.cbegin(), path.cend(), [](char c) { return c == '.'; });
}

zx_status_t GetDirectory(vfs::PseudoDir* dir, std::string name, bool create_if_empty,
                         vfs::PseudoDir** out) {
  if (!IsPathValid(name)) {
    return ZX_ERR_INVALID_ARGS;
  }

  vfs::internal::Node* node = nullptr;
  zx_status_t status = dir->Lookup(name, &node);
  if (status != ZX_OK) {
    if (!create_if_empty) {
      return status;
    }

    return AddNewEmptyDirectory(dir, std::move(name), out);
  }

  *out = static_cast<vfs::PseudoDir*>(node);
  return ZX_OK;
}

zx_status_t GetDirectoryByPath(vfs::PseudoDir* root, std::string path, bool create_if_empty,
                               vfs::PseudoDir** out) {
  *out = root;

  // If empty, return root directory.
  if (path.empty()) {
    return ZX_OK;
  }

  // Don't allow leading nor trailing slashes.
  if (path[0] == kPathDelimiter || path[path.size() - 1] == kPathDelimiter) {
    return ZX_ERR_INVALID_ARGS;
  }

  size_t start_pos = 0;
  size_t end_pos = path.find(kPathDelimiter);

  while (end_pos != std::string::npos) {
    std::string current_path = path.substr(start_pos, end_pos - start_pos);
    zx_status_t status = GetDirectory(*out, current_path, create_if_empty, out);
    if (status != ZX_OK) {
      return status;
    }

    start_pos = end_pos + kPathDelimiterSize;
    end_pos = path.find(kPathDelimiter, start_pos);
  }

  return GetDirectory(*out, path.substr(start_pos), create_if_empty, out);
}

zx_status_t AddServiceEntry(vfs::PseudoDir* node, const std::string& service_name, void* context,
                            svc_connector_t handler) {
  return node->AddEntry(
      service_name,
      std::make_unique<vfs::Service>([service_name = std::string(service_name), context, handler](
                                         zx::channel channel, async_dispatcher_t* dispatcher) {
        // We drop |dispatcher| on the floor because the libsvc.so
        // declaration of |svc_connector_t| doesn't receive a
        // |dispatcher|. Callees are likely to use the default
        // |async_dispatcher_t| for the current thread.
        handler(context, service_name.c_str(), channel.release());
      }));
}

}  // namespace

struct svc_dir {
  std::unique_ptr<vfs::PseudoDir> impl = std::make_unique<vfs::PseudoDir>();
};

zx_status_t svc_dir_create(async_dispatcher_t* dispatcher, zx_handle_t dir_request,
                           svc_dir_t** result) {
  svc_dir_create_without_serve(result);
  zx_status_t status = svc_dir_serve(*result, dispatcher, dir_request);
  if (status != ZX_OK) {
    svc_dir_destroy(*result);
    return status;
  }

  return ZX_OK;
}

zx_status_t svc_dir_create_without_serve(svc_dir_t** result) {
  *result = new svc_dir_t;
  return ZX_OK;
}

zx_status_t svc_dir_serve(svc_dir_t* dir, async_dispatcher_t* dispatcher, zx_handle_t request) {
  if (dir == nullptr) {
    return ZX_ERR_INVALID_ARGS;
  }

  return dir->impl->Serve(
      fuchsia::io::OpenFlags::RIGHT_READABLE | fuchsia::io::OpenFlags::RIGHT_WRITABLE,
      zx::channel(request), dispatcher);
}

zx_status_t svc_dir_add_service(svc_dir_t* dir, const char* type, const char* service_name,
                                void* context, svc_connector_t handler) {
  const char* path = type == nullptr ? "" : type;
  return svc_dir_add_service_by_path(dir, path, service_name, context, handler);
}

zx_status_t svc_dir_add_service_by_path(svc_dir_t* dir, const char* path, const char* service_name,
                                        void* context, svc_connector_t* handler) {
  vfs::PseudoDir* node = nullptr;
  zx_status_t status = GetDirectoryByPath(dir->impl.get(), path, /*create_if_empty=*/true, &node);
  if (status != ZX_OK) {
    return status;
  }

  return AddServiceEntry(node, service_name, context, handler);
}

zx_status_t svc_dir_add_directory(svc_dir_t* dir, const char* name, zx_handle_t subdir) {
  if (dir == nullptr || name == nullptr || subdir == ZX_HANDLE_INVALID) {
    return ZX_ERR_INVALID_ARGS;
  }

  auto remote_dir = std::make_unique<vfs::RemoteDir>(zx::channel(subdir));
  return dir->impl->AddEntry(name, std::move(remote_dir));
}

zx_status_t svc_dir_remove_service(svc_dir_t* dir, const char* type, const char* service_name) {
  const char* path = type == nullptr ? "" : type;
  return svc_dir_remove_service_by_path(dir, path, service_name);
}

zx_status_t svc_dir_remove_service_by_path(svc_dir_t* dir, const char* path,
                                           const char* service_name) {
  vfs::PseudoDir* node = nullptr;
  zx_status_t status = GetDirectoryByPath(dir->impl.get(), path, /*create_if_empty=*/false, &node);
  if (status != ZX_OK) {
    return status;
  }

  return node->RemoveEntry(service_name);
}

zx_status_t svc_dir_remove_directory(svc_dir_t* dir, const char* name) {
  if (dir == nullptr || name == nullptr) {
    return ZX_ERR_INVALID_ARGS;
  }

  return dir->impl->RemoveEntry(name);
}

zx_status_t svc_dir_destroy(svc_dir_t* dir) {
  delete dir;
  return ZX_OK;
}
