// Copyright 2019 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 "local-vnode.h"

#include <lib/zx/channel.h>
#include <lib/zxio/ops.h>
#include <lib/zxio/zxio.h>
#include <zircon/types.h>

#include <utility>

#include <fbl/auto_lock.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include <fbl/string.h>
#include <fbl/string_buffer.h>

#include "sdk/lib/fdio/internal.h"
#include "sdk/lib/fdio/zxio.h"

namespace fdio_internal {

zx_status_t LocalVnode::AddChild(fbl::RefPtr<LocalVnode> child) {
  return std::visit(fdio::overloaded{
                        [](LocalVnode::Local& c) {
                          // Calling AddChild on a Local node is invalid.
                          return ZX_ERR_NOT_DIR;
                        },
                        [&child](LocalVnode::Intermediate& c) {
                          c.AddEntry(child);
                          return ZX_OK;
                        },
                        [](LocalVnode::Remote& s) {
                          // Calling AddChild on a Storage node is invalid, and implies
                          // a poorly formed path.
                          return ZX_ERR_BAD_PATH;
                        },
                    },
                    node_type_);
}

void LocalVnode::Intermediate::AddEntry(fbl::RefPtr<LocalVnode> vn) {
  // |fdio_namespace| already checked that the entry does not exist.
  ZX_DEBUG_ASSERT(entries_by_name_.find(vn->Name()) == entries_by_name_.end());

  auto entry = std::make_unique<Entry>(next_node_id_, std::move(vn));
  entries_by_name_.insert(entry.get());
  entries_by_id_.insert(std::move(entry));
  next_node_id_++;
}

zx_status_t LocalVnode::RemoveChild(LocalVnode* child) {
  return std::visit(fdio::overloaded{
                        [](LocalVnode::Local& c) {
                          // Calling RemoveChild on a Local node fails.
                          return ZX_ERR_NOT_FOUND;
                        },
                        [&child](LocalVnode::Intermediate& c) {
                          c.RemoveEntry(child);
                          return ZX_OK;
                        },
                        [](LocalVnode::Remote& s) {
                          // Calling RemoveChild on a Storage node is invalid, and implies
                          // a poorly formed path.
                          return ZX_ERR_BAD_PATH;
                        },
                    },
                    node_type_);
}

void LocalVnode::Intermediate::RemoveEntry(LocalVnode* vn) {
  auto it = entries_by_name_.find(vn->Name());
  if (it != entries_by_name_.end() && it->node().get() == vn) {
    auto id = it->id();
    entries_by_name_.erase(it);
    entries_by_id_.erase(id);
  }
}

void LocalVnode::Unlink() {
  std::visit(fdio::overloaded{
                 [](LocalVnode::Local& c) { c.Unlink(); },
                 [](LocalVnode::Intermediate& c) { c.UnlinkEntries(); },
                 [](LocalVnode::Remote& s) {},
             },
             node_type_);
  UnlinkFromParent();
}

fbl::RefPtr<LocalVnode> LocalVnode::Intermediate::Lookup(std::string_view name) const {
  auto it = entries_by_name_.find(fbl::String{name});
  if (it != entries_by_name_.end()) {
    return it->node();
  }
  return nullptr;
}

LocalVnode::~LocalVnode() {
  std::visit(fdio::overloaded{
                 [](LocalVnode::Local& c) {},
                 [](LocalVnode::Intermediate& c) {},
                 [](LocalVnode::Remote& s) {
                   // Close the channel underlying the remote connection without making a Close
                   // call to preserve previous behavior.
                   zx::channel remote_channel;
                   zxio_release(s.Connection(), remote_channel.reset_and_get_address());
                 },
             },
             node_type_);
}

void LocalVnode::Intermediate::UnlinkEntries() {
  for (auto& entry : entries_by_name_) {
    std::visit(fdio::overloaded{
                   [](LocalVnode::Local& c) {},
                   [](LocalVnode::Intermediate& c) { c.UnlinkEntries(); },
                   [](LocalVnode::Remote& s) {},
               },
               entry.node()->node_type_);
    entry.node()->parent_ = nullptr;
  }
  entries_by_name_.clear();
  entries_by_id_.clear();
}

LocalVnode::Local::Local(fdio_open_local_func_t on_open, void* context)
    : on_open_(on_open), context_(context) {}

zx::result<fdio_ptr> LocalVnode::Local::Open() {
  fbl::AutoLock lock(&lock_);
  if (on_open_ == nullptr) {
    return zx::error(ZX_ERR_BAD_HANDLE);
  }

  fdio_ptr io = fbl::MakeRefCounted<zxio>();
  if (io == nullptr) {
    return zx::error(ZX_ERR_NO_MEMORY);
  }
  zxio_ops_t const* ops = nullptr;
  zx_status_t status = on_open_(&io->zxio_storage(), context_, &ops);
  if (status != ZX_OK) {
    return zx::error(status);
  }
  zxio_init(&io->zxio_storage().io, ops);
  return zx::ok(io);
}

void LocalVnode::Local::Unlink() {
  fbl::AutoLock lock(&lock_);
  on_open_ = nullptr;
  context_ = nullptr;
}

void LocalVnode::UnlinkFromParent() {
  if (parent_) {
    parent_->RemoveChild(this);
  }
  parent_ = nullptr;
}

zx_status_t LocalVnode::EnumerateInternal(PathBuffer* path, const EnumerateCallback& func) const {
  const size_t original_length = path->length();

  // Add this current node to the path, and enumerate it if it has a remote
  // object.
  path->Append(Name().data(), Name().length());

  std::visit(fdio::overloaded{
                 [](const LocalVnode::Local& c) {
                   // Nothing to do as the node has no children and is not a
                   // remote node.
                 },
                 [&path, &func, this](const LocalVnode::Intermediate& c) {
                   // If we added a node with children, add a separator and enumerate all the
                   // children.
                   if (Name().length() > 0) {
                     path->Append('/');
                   }

                   c.ForAllEntries([&path, &func](const LocalVnode& child) {
                     return child.EnumerateInternal(path, func);
                   });
                 },
                 [&path, &func](const LocalVnode::Remote& s) {
                   // If we added a remote node, call the enumeration function on the remote node.
                   func(std::string_view(path->data(), path->length()), s.Connection());
                 },
             },
             node_type_);

  // To re-use the same prefix buffer, restore the original buffer length
  // after enumeration has completed.
  path->Resize(original_length);
  return ZX_OK;
}

zx_status_t LocalVnode::EnumerateRemotes(const EnumerateCallback& func) const {
  PathBuffer path;
  path.Append('/');
  return EnumerateInternal(&path, func);
}

zx_status_t LocalVnode::Readdir(uint64_t* last_seen, fbl::RefPtr<LocalVnode>* out_vnode) const {
  return std::visit(fdio::overloaded{
                        [&](const LocalVnode::Local& c) {
                          // Calling readdir on a Local node is invalid.
                          return ZX_ERR_NOT_DIR;
                        },
                        [&](const LocalVnode::Intermediate& c) {
                          for (auto it = c.GetEntriesById().lower_bound(*last_seen);
                               it != c.GetEntriesById().end(); ++it) {
                            if (it->id() <= *last_seen) {
                              continue;
                            }
                            *last_seen = it->id();
                            *out_vnode = it->node();
                            return ZX_OK;
                          }
                          *out_vnode = nullptr;
                          return ZX_OK;
                        },
                        [](const LocalVnode::Remote& s) {
                          // If we've called Readdir on a Remote node, the path
                          // was misconfigured.
                          return ZX_ERR_BAD_PATH;
                        },
                    },
                    node_type_);
}

template <typename Fn>
zx_status_t LocalVnode::Intermediate::ForAllEntries(Fn fn) const {
  for (const Entry& entry : entries_by_id_) {
    zx_status_t status = fn(*entry.node());
    if (status != ZX_OK) {
      return status;
    }
  }
  return ZX_OK;
}

}  // namespace fdio_internal
