// 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;
  } else {
    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, fuchsia::io::DIRENT_TYPE_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 = fuchsia::io::DIRENT_TYPE_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_.size() == 0;
}

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
