// 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 <lib/fdio/vfs.h>
#include <lib/vfs/cpp/internal/dirent_filler.h>
#include <lib/vfs/cpp/pseudo_dir.h>

#include <mutex>

namespace vfs {

PseudoDir::PseudoDir() : next_node_id_(kDotId + 1) {}

PseudoDir::~PseudoDir() = default;

zx_status_t PseudoDir::AddSharedEntry(std::string name, std::shared_ptr<Node> vn) {
  ZX_DEBUG_ASSERT(vn);

  auto id = next_node_id_++;
  return AddEntry(std::make_unique<SharedEntry>(id, std::move(name), std::move(vn)));
}

zx_status_t PseudoDir::AddEntry(std::string name, std::unique_ptr<Node> vn) {
  ZX_DEBUG_ASSERT(vn);

  auto id = next_node_id_++;
  return AddEntry(std::make_unique<UniqueEntry>(id, std::move(name), std::move(vn)));
}

zx_status_t PseudoDir::AddEntry(std::unique_ptr<Entry> entry) {
  ZX_DEBUG_ASSERT(entry);

  if (!vfs::internal::IsValidName(entry->name())) {
    return ZX_ERR_INVALID_ARGS;
  }

  std::lock_guard<std::mutex> guard(mutex_);

  if (entries_by_name_.find(entry->name()) != entries_by_name_.end()) {
    return ZX_ERR_ALREADY_EXISTS;
  }
  entries_by_name_[entry->name()] = entry.get();
  auto id = entry->id();
  entries_by_id_.emplace_hint(entries_by_id_.end(), id, std::move(entry));

  return ZX_OK;
}

zx_status_t PseudoDir::RemoveEntry(const std::string& name) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto entry = entries_by_name_.find(name);
  if (entry == entries_by_name_.end()) {
    return ZX_ERR_NOT_FOUND;
  }
  entries_by_id_.erase(entry->second->id());
  entries_by_name_.erase(name);

  return ZX_OK;
}

zx_status_t PseudoDir::RemoveEntry(const std::string& name, Node* node) {
  std::lock_guard<std::mutex> guard(mutex_);
  auto entry = entries_by_name_.find(name);
  if (entry == entries_by_name_.end() || entry->second->node() != node) {
    return ZX_ERR_NOT_FOUND;
  }
  entries_by_id_.erase(entry->second->id());
  entries_by_name_.erase(name);

  return ZX_OK;
}

zx_status_t PseudoDir::Lookup(const std::string& name, vfs::internal::Node** out_node) const {
  std::lock_guard<std::mutex> guard(mutex_);

  auto search = entries_by_name_.find(name);
  if (search != entries_by_name_.end()) {
    *out_node = search->second->node();
    return ZX_OK;
  }
  return ZX_ERR_NOT_FOUND;
}

zx_status_t PseudoDir::Readdir(uint64_t offset, void* data, uint64_t len, uint64_t* out_offset,
                               uint64_t* out_actual) {
  vfs::internal::DirentFiller df(data, len);
  *out_actual = 0;
  *out_offset = offset;
  if (offset < kDotId) {
    if (df.Next(".", 1, static_cast<uint8_t>(fuchsia::io::DirentType::DIRECTORY),
                fuchsia::io::INO_UNKNOWN) != ZX_OK) {
      *out_actual = df.GetBytesFilled();
      return ZX_ERR_INVALID_ARGS;  // out_actual would be 0
    }
    (*out_offset)++;
  }

  std::lock_guard<std::mutex> guard(mutex_);

  for (auto it = entries_by_id_.upper_bound(*out_offset); it != entries_by_id_.end(); ++it) {
    fuchsia::io::NodeAttributes attr;
    auto d_type = static_cast<uint8_t>(fuchsia::io::DirentType::UNKNOWN);
    auto ino = fuchsia::io::INO_UNKNOWN;
    if (it->second->node()->GetAttr(&attr) == ZX_OK) {
      d_type = ((fuchsia::io::MODE_TYPE_MASK & attr.mode) >> 12);
      ino = attr.id;
    }

    if (df.Next(it->second->name(), d_type, ino) != ZX_OK) {
      *out_actual = df.GetBytesFilled();
      if (*out_actual == 0) {
        // no space to fill even 1 dentry
        return ZX_ERR_INVALID_ARGS;
      }
      return ZX_OK;
    }
    *out_offset = it->second->id();
  }

  *out_actual = df.GetBytesFilled();
  return ZX_OK;
}

bool PseudoDir::IsEmpty() const {
  std::lock_guard<std::mutex> guard(mutex_);
  return entries_by_name_.empty();
}

PseudoDir::Entry::Entry(uint64_t id, std::string name) : id_(id), name_(std::move(name)) {}

PseudoDir::Entry::~Entry() = default;

PseudoDir::SharedEntry::SharedEntry(uint64_t id, std::string name, std::shared_ptr<Node> node)
    : Entry(id, std::move(name)), node_(std::move(node)) {}

vfs::internal::Node* PseudoDir::SharedEntry::node() const { return node_.get(); }

PseudoDir::SharedEntry::~SharedEntry() = default;

PseudoDir::UniqueEntry::UniqueEntry(uint64_t id, std::string name, std::unique_ptr<Node> node)
    : Entry(id, std::move(name)), node_(std::move(node)) {}

vfs::internal::Node* PseudoDir::UniqueEntry::node() const { return node_.get(); }

PseudoDir::UniqueEntry::~UniqueEntry() = default;

}  // namespace vfs
