// 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 <fidl/fuchsia.io/cpp/wire.h>
#include <lib/svc/dir.h>
#include <lib/zx/channel.h>
#include <zircon/assert.h>
#include <zircon/errors.h>
#include <zircon/types.h>

#include <algorithm>
#include <memory>
#include <utility>

#include <fbl/ref_ptr.h>
#include <src/lib/storage/vfs/cpp/pseudo_dir.h>
#include <src/lib/storage/vfs/cpp/remote_dir.h>
#include <src/lib/storage/vfs/cpp/service.h>
#include <src/lib/storage/vfs/cpp/synchronous_vfs.h>
#include <src/lib/storage/vfs/cpp/vnode.h>

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(fbl::RefPtr<fs::PseudoDir> dir, const std::string& name,
                                 fbl::RefPtr<fs::PseudoDir>* out) {
  auto subdir = fbl::MakeRefCounted<fs::PseudoDir>();
  zx_status_t status = dir->AddEntry(name, subdir);
  if (status == ZX_OK) {
    *out = subdir;
  }
  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(fbl::RefPtr<fs::PseudoDir> dir, const std::string& name,
                         bool create_if_empty, fbl::RefPtr<fs::PseudoDir>* out) {
  if (!IsPathValid(name)) {
    return ZX_ERR_INVALID_ARGS;
  }

  fbl::RefPtr<fs::Vnode> node = nullptr;
  zx_status_t status = dir->Lookup(name, &node);
  if (status != ZX_OK) {
    if (!create_if_empty) {
      return status;
    }

    return AddNewEmptyDirectory(dir, name, out);
  }

  *out = fbl::RefPtr<fs::PseudoDir>::Downcast(node);

  return ZX_OK;
}

zx_status_t GetDirectoryByPath(fbl::RefPtr<fs::PseudoDir> root, const std::string& path,
                               bool create_if_empty, fbl::RefPtr<fs::PseudoDir>* out) {
  *out = std::move(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(fbl::RefPtr<fs::PseudoDir> node, const std::string& service_name,
                            void* context, svc_connector_t handler) {
  return node->AddEntry(service_name,
                        fbl::MakeRefCounted<fs::Service>([service_name = std::string(service_name),
                                                          context, handler](zx::channel channel) {
                          handler(context, service_name.c_str(), channel.release());

                          return ZX_OK;
                        }));
}

}  // namespace

struct svc_dir {
  std::unique_ptr<fs::SynchronousVfs> vfs = nullptr;
  fbl::RefPtr<fs::PseudoDir> root = fbl::MakeRefCounted<fs::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;
  }

  if (dir->vfs == nullptr) {
    dir->vfs = std::make_unique<fs::SynchronousVfs>(dispatcher);
  }

  return dir->vfs->Serve(dir->root, zx::channel(request), fs::VnodeConnectionOptions::ReadWrite());
}

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) {
  fbl::RefPtr<fs::PseudoDir> node;
  zx_status_t status = GetDirectoryByPath(dir->root, 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;
  }

  fidl::ClientEnd<fuchsia_io::Directory> client_end((zx::channel(subdir)));
  auto remote_dir = fbl::MakeRefCounted<fs::RemoteDir>(std::move(client_end));
  return dir->root->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) {
  fbl::RefPtr<fs::PseudoDir> parent_directory;
  zx_status_t status =
      GetDirectoryByPath(dir->root, path, /*create_if_empty=*/false, &parent_directory);
  if (status != ZX_OK) {
    return status;
  }

  fbl::RefPtr<fs::Vnode> service_node;
  status = parent_directory->Lookup(service_name, &service_node);
  if (status != ZX_OK) {
    return status;
  }
  status = parent_directory->RemoveEntry(service_name, service_node.get());
  if (status == ZX_OK) {
    dir->vfs->CloseAllConnectionsForVnode(*service_node, nullptr);
  }

  return status;
}

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->root->RemoveEntry(name);
}

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