// 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.

#ifndef LIB_FDIO_NAMESPACE_LOCAL_VNODE_H_
#define LIB_FDIO_NAMESPACE_LOCAL_VNODE_H_

#include <fidl/fuchsia.io/cpp/wire.h>
#include <lib/fdio/cleanpath.h>
#include <lib/fdio/namespace.h>
#include <lib/fit/function.h>
#include <lib/zx/channel.h>
#include <lib/zx/result.h>
#include <lib/zxio/types.h>
#include <limits.h>
#include <zircon/types.h>

#include <utility>

#include <fbl/intrusive_wavl_tree.h>
#include <fbl/macros.h>
#include <fbl/mutex.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"

namespace fdio_internal {

using EnumerateCallback = fit::function<zx_status_t(std::string_view path, zxio_t* entry)>;

// Represents a mapping from a string name to a remote connection.
//
// Each LocalVnode may have named children, which themselves may also
// optionally represent remote connections.
//
// This class is thread-compatible.
class LocalVnode : public fbl::RefCounted<LocalVnode> {
 public:
  DISALLOW_COPY_ASSIGN_AND_MOVE(LocalVnode);

  // Initializes a new vnode with a remote node_type, and attaches a reference to it
  // inside an (optional) parent.
  template <class T, class... Args>
  static zx::result<fbl::RefPtr<LocalVnode>> Create(fbl::RefPtr<LocalVnode> parent,
                                                    fbl::String name,
                                                    std::in_place_type_t<T> in_place,
                                                    Args&&... args) {
    fbl::RefPtr vn = fbl::AdoptRef(
        new LocalVnode(std::move(parent), std::move(name), in_place, std::forward<Args>(args)...));

    if (vn->parent_ != nullptr) {
      zx_status_t status = vn->parent_->AddChild(vn);
      if (status != ZX_OK) {
        return zx::error(status);
      }
    }

    return zx::ok(vn);
  }

  // Recursively unlinks this Vnode's children, and detaches this node from
  // its parent.
  void Unlink();

  // Detaches this vnode from its parent. The Vnode's own children are not unlinked.
  void UnlinkFromParent();

  // Returns the next child vnode from the list of children, assuming that
  // |last_seen| is the ID of the last returned vnode. At the same time,
  // |last_seen| is updated to reflect the current ID.
  //
  // If the end of iteration is reached, |out_vnode| is set to nullptr.
  zx_status_t Readdir(uint64_t* last_seen, fbl::RefPtr<LocalVnode>* out_vnode) const;

  // Invoke |func| on the (path, channel) pairs for all remote nodes found in the
  // node hierarchy rooted at `this`.
  zx_status_t EnumerateRemotes(const EnumerateCallback& func) const;

  const fbl::String& Name() const { return name_; }

  struct IdTreeTag {};
  struct NameTreeTag {};

  class Entry : public fbl::ContainableBaseClasses<
                    fbl::TaggedWAVLTreeContainable<std::unique_ptr<Entry>, IdTreeTag,
                                                   fbl::NodeOptions::AllowMultiContainerUptr>,
                    fbl::TaggedWAVLTreeContainable<Entry*, NameTreeTag>> {
   public:
    Entry(uint64_t id, fbl::RefPtr<LocalVnode> node) : id_(id), node_(std::move(node)) {}
    ~Entry() = default;

    uint64_t id() const { return id_; }
    const fbl::String& name() const { return node_->name_; }
    const fbl::RefPtr<LocalVnode>& node() const { return node_; }

   private:
    uint64_t const id_;
    fbl::RefPtr<LocalVnode> node_;
  };

  struct KeyByIdTraits {
    static uint64_t GetKey(const Entry& entry) { return entry.id(); }
    static bool LessThan(uint64_t key1, uint64_t key2) { return key1 < key2; }
    static bool EqualTo(uint64_t key1, uint64_t key2) { return key1 == key2; }
  };

  struct KeyByNameTraits {
    static fbl::String GetKey(const Entry& entry) { return entry.name(); }
    static bool LessThan(const fbl::String& key1, const fbl::String& key2) { return key1 < key2; }
    static bool EqualTo(const fbl::String& key1, const fbl::String& key2) { return key1 == key2; }
  };

  using EntryByIdMap =
      fbl::TaggedWAVLTree<uint64_t, std::unique_ptr<Entry>, IdTreeTag, KeyByIdTraits>;
  using EntryByNameMap = fbl::TaggedWAVLTree<fbl::String, Entry*, NameTreeTag, KeyByNameTraits>;

  class Intermediate {
   public:
    bool has_children() const { return !entries_by_id_.is_empty(); }
    void AddEntry(fbl::RefPtr<LocalVnode> vn);
    void RemoveEntry(LocalVnode* vn);
    void UnlinkEntries();

    const EntryByIdMap& GetEntriesById() const { return entries_by_id_; }

    // Returns a child if it has the name |name|.
    // Otherwise, returns nullptr.
    fbl::RefPtr<LocalVnode> Lookup(std::string_view name) const;

    // Invoke |Fn()| on all entries in this Intermediate node_type.
    // May be used as a const visitor-pattern for all entries.
    //
    // Any status other than ZX_OK returned from |Fn()| will halt iteration
    // immediately and return.
    template <typename Fn>
    zx_status_t ForAllEntries(Fn fn) const;

   private:
    uint64_t next_node_id_ = 1;
    EntryByNameMap entries_by_name_;
    EntryByIdMap entries_by_id_;
  };

  class Local {
   public:
    Local(fdio_open_local_func_t on_open, void* context);
    zx::result<fdio_ptr> Open();
    void Unlink();

   private:
    fbl::Mutex lock_;
    fdio_open_local_func_t on_open_ __TA_GUARDED(lock_);
    void* context_ __TA_GUARDED(lock_);
  };

  class Remote {
   public:
    explicit Remote(zxio_storage_t remote_storage) : remote_storage_(remote_storage) {}
    zxio_t* Connection() const { return const_cast<zxio_t*>(&remote_storage_.io); }

   private:
    const zxio_storage_t remote_storage_;
  };

  std::variant<Local, Intermediate, Remote>& NodeType() { return node_type_; }

 private:
  friend class fbl::RefPtr<LocalVnode>;

  zx_status_t AddChild(fbl::RefPtr<LocalVnode> child);
  zx_status_t RemoveChild(LocalVnode* child);

  zx_status_t EnumerateInternal(PathBuffer* path, const EnumerateCallback& func) const;

  template <class T, class... Args>
  LocalVnode(fbl::RefPtr<LocalVnode> parent, fbl::String name, std::in_place_type_t<T> in_place,
             Args&&... args)
      : node_type_(in_place, std::forward<Args>(args)...),
        parent_(std::move(parent)),
        name_(std::move(name)) {}
  ~LocalVnode();

  std::variant<Local, Intermediate, Remote> node_type_;
  fbl::RefPtr<LocalVnode> parent_;
  const fbl::String name_;
};

}  // namespace fdio_internal

#endif  // LIB_FDIO_NAMESPACE_LOCAL_VNODE_H_
