// 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/fit/optional.h>
#include <lib/inspect/cpp/reader.h>
#include <lib/inspect/cpp/vmo/block.h>
#include <lib/inspect/cpp/vmo/scanner.h>
#include <lib/inspect/cpp/vmo/snapshot.h>

#include <iterator>
#include <set>
#include <stack>
#include <unordered_map>

using inspect::internal::BlockIndex;
using inspect::internal::SnapshotTree;

namespace inspect {

namespace {

// Traverses the given hierarchy and passes pointers to any hierarchy containing a link to the
// callback.
//
// The callback is called before the passed hierarchy is traversed into, so it may be modified in
// the context of the callback.
void VisitHierarchiesWithLink(Hierarchy* root, fit::function<void(Hierarchy*)> callback) {
  root->Visit([&](const std::vector<std::string>& path, Hierarchy* hierarchy) {
    if (!hierarchy->node().links().empty()) {
      callback(hierarchy);
    }
    return true;
  });
}

// Iteratively snapshot individual inspectors and then snapshot the children of those inspectors,
// collecting the results in a single SnapshotTree.
//
// Consistency of individual Snapshots is guaranteed.
//
// Child Snapshots are guaranteed only to be taken consistently after their parent Snapshot.
//
// Between the initial Snapshot and reading lazy children, it is possible that the lazy child was
// deleted. In this case, the child snapshot will be missing.
fit::promise<SnapshotTree> SnapshotTreeFromInspector(Inspector insp) {
  SnapshotTree ret;
  if (ZX_OK != Snapshot::Create(insp.DuplicateVmo(), &ret.snapshot)) {
    return fit::make_result_promise<SnapshotTree>(fit::error());
  }

  // Sequence all promises to ensure depth-first traversal. Otherwise traversal may cause
  // all children for a Snapshot to be instantiated simultaneously.
  fit::sequencer seq;
  std::vector<fit::promise<SnapshotTree>> promises;
  auto child_names = insp.GetChildNames();
  for (const auto& child_name : child_names) {
    promises.emplace_back(
        insp.OpenChild(child_name)
            .and_then([](Inspector& insp) { return SnapshotTreeFromInspector(std::move(insp)); })
            .wrap_with(seq));
  }

  return fit::join_promise_vector(std::move(promises))
      .and_then([ret = std::move(ret), names = std::move(child_names)](
                    std::vector<fit::result<SnapshotTree>>& children) mutable
                -> fit::result<SnapshotTree> {
        ZX_ASSERT(names.size() == children.size());

        for (size_t i = 0; i < names.size(); i++) {
          if (children[i].is_ok()) {
            ret.children.emplace(std::move(names[i]), children[i].take_value());
          }
        }

        return fit::ok(std::move(ret));
      });
}

}  // namespace

namespace internal {

// A ParsedNode contains parsed information for a node.
// It is built iteratively as children and values are discovered.
//
// A ParsedNode is valid only if it has been initialized with a name and
// parent index (which happens when its OBJECT_VALUE block is read).
//
// A ParsedNode is "complete" when the number of children in the parsed
// hierarchy matches an expected count. At this point the Hierarchy may be
// removed and the ParsedNode discarded.
struct ParsedNode {
  // The node hierarchy being parsed out of the buffer.
  // Propertys and properties are parsed into here as they are read.
  Hierarchy hierarchy;

  // The number of children expected for this node.
  // The node is considered "complete" once the number of children in the
  // hierarchy matches this count.
  size_t children_count = 0;

  // The index of the parent, only valid if this node is initialized.
  BlockIndex parent;

  // Initializes the stored node with the given name and parent.
  void InitializeNode(std::string name, BlockIndex new_parent) {
    hierarchy.node_ptr()->set_name(std::move(name));
    parent = new_parent;
    initialized_ = true;
  }

  explicit operator bool() { return initialized_; }

  bool is_complete() { return hierarchy.children().size() == children_count; }

 private:
  bool initialized_ = false;
};

// The |Reader| supports reading the contents of a |Snapshot|.
// This class constructs a hierarchy of nodes contained in the snapshot
// if the snapshot is valid.
class Reader {
 public:
  Reader(Snapshot snapshot) : snapshot_(std::move(snapshot)) {}

  // Read the contents of the snapshot and return the root node.
  fit::result<Hierarchy> Read();

 private:
  // Gets a pointer to the ParsedNode for the given index. A new ParsedObject
  // is created if one did not exist previously for the index.
  ParsedNode* GetOrCreate(BlockIndex index);

  void InnerScanBlocks();

  // Initialize an Object for the given BlockIndex.
  void InnerCreateObject(BlockIndex index, const Block* block);

  // Parse a numeric property block and attach it to the given parent.
  void InnerParseNumericProperty(ParsedNode* parent, const Block* block);

  // Parse a property block and attach it to the given parent.
  void InnerParseProperty(ParsedNode* parent, const Block* block);

  // Parse a link block and attach it to the given parent.
  void InnerParseLink(ParsedNode* parent, const Block* block);

  // Helper to interpret the given block as a NAME block and return a
  // copy of the name contents.
  fit::optional<std::string> GetAndValidateName(BlockIndex index);

  // Contents of the read VMO.
  Snapshot snapshot_;

  // Map of block index to the parsed node being constructed for that address.
  std::unordered_map<BlockIndex, ParsedNode> parsed_nodes_;
};

fit::optional<std::string> Reader::GetAndValidateName(BlockIndex index) {
  const Block* block = internal::GetBlock(&snapshot_, index);
  if (!block) {
    return {};
  }

  size_t capacity = PayloadCapacity(GetOrder(block));
  auto len = NameBlockFields::Length::Get<size_t>(block->header);
  // Do not parse the name if the declared length is greater than what the block can hold.
  if (len > capacity) {
    return {};
  }

  return std::string(block->payload_ptr(), len);
}

void Reader::InnerScanBlocks() {
  ScanBlocks(snapshot_.data(), snapshot_.size(), [this](BlockIndex index, const Block* block) {
    BlockType type = GetType(block);
    if (index == 0) {
      if (type != BlockType::kHeader) {
        return false;
      }
    } else if (type == BlockType::kNodeValue) {
      // This block defines an Object, use the value to fill out the name of
      // the ParsedNode.
      InnerCreateObject(index, block);
    } else if (type == BlockType::kIntValue || type == BlockType::kUintValue ||
               type == BlockType::kDoubleValue || type == BlockType::kArrayValue ||
               type == BlockType::kBoolValue) {
      // This block defines a numeric property for an Object, parse the
      // property into the properties field of the ParsedNode.
      auto parent_index = ValueBlockFields::ParentIndex::Get<BlockIndex>(block->header);
      InnerParseNumericProperty(GetOrCreate(parent_index), block);
    } else if (type == BlockType::kBufferValue) {
      // This block defines a property for an Object, parse the property
      // into the properties field of the ParsedNode.
      auto parent_index = ValueBlockFields::ParentIndex::Get<BlockIndex>(block->header);
      InnerParseProperty(GetOrCreate(parent_index), block);
    } else if (type == BlockType::kLinkValue) {
      // This block defines a link to an adjacent hierarchy stored outside the currently parsed one.
      // For now we parse and store the contents of the link with the NodeValue, and we will handle
      // merging trees in a separate step.
      auto parent_index = ValueBlockFields::ParentIndex::Get<BlockIndex>(block->header);
      InnerParseLink(GetOrCreate(parent_index), block);
    }

    return true;
  });
}

fit::result<Hierarchy> Reader::Read() {
  if (!snapshot_) {
    // Snapshot is invalid, return an error.
    return fit::error();
  }

  // Initialize the implicit root node, which uses index 0.
  ParsedNode root;
  root.InitializeNode("root", 0);
  parsed_nodes_.emplace(0, std::move(root));

  // Scan blocks into the parsed_node map. This creates ParsedNodes with
  // properties and an accurate count of the number of expected
  // children. ParsedNodes with a valid OBJECT_VALUE block are initialized
  // with a name and parent index.
  InnerScanBlocks();

  // Stack of completed nodes to process. Entries consist of the completed
  // Hierarchy and the block index of their parent.
  std::stack<std::pair<Hierarchy, BlockIndex>> complete_nodes;

  // Iterate over the map of parsed nodes and find those nodes that are
  // already "complete." These nodes are moved to the complete_nodes map for
  // bottom-up processing.
  for (auto it = parsed_nodes_.begin(); it != parsed_nodes_.end();) {
    if (!it->second) {
      // The node is not valid, ignore.
      it = parsed_nodes_.erase(it);
      continue;
    }

    if (it->second.is_complete()) {
      if (it->first == 0) {
        // The root is complete, return it.
        return fit::ok(std::move(it->second.hierarchy));
      }

      // The node is valid and complete, push it onto the stack.
      complete_nodes.push(std::make_pair(std::move(it->second.hierarchy), it->second.parent));
      it = parsed_nodes_.erase(it);
      continue;
    }

    ++it;
  }

  // Construct a valid hierarchy from the bottom up by attaching completed
  // nodes to their parent node. Once a parent becomes complete, add it to
  // the stack to recursively bubble the completed children towards the root.
  while (!complete_nodes.empty()) {
    auto obj = std::move(complete_nodes.top());
    complete_nodes.pop();

    // Get the parent node, which was created during block scanning.
    auto it = parsed_nodes_.find(obj.second);
    if (it == parsed_nodes_.end()) {
      // Parent node did not exist, ignore this node.
      continue;
    }
    auto* parent = &it->second;
    parent->hierarchy.add_child(std::move(obj.first));
    if (parent->is_complete()) {
      if (obj.second == 0) {
        // This was the last node that needed to be added to the root to complete it.
        // Return the root.
        return fit::ok(std::move(parent->hierarchy));
      }

      // The parent node is now complete, push it onto the stack.
      complete_nodes.push(std::make_pair(std::move(parent->hierarchy), parent->parent));
      parsed_nodes_.erase(it);
    }
  }

  // We processed all completed nodes but could not find a complete root,
  // return an error.
  return fit::error();
}

ParsedNode* Reader::GetOrCreate(BlockIndex index) {
  return &parsed_nodes_.emplace(index, ParsedNode()).first->second;
}

ArrayDisplayFormat ArrayBlockFormatToDisplay(ArrayBlockFormat format) {
  switch (format) {
    case ArrayBlockFormat::kLinearHistogram:
      return ArrayDisplayFormat::kLinearHistogram;
    case ArrayBlockFormat::kExponentialHistogram:
      return ArrayDisplayFormat::kExponentialHistogram;
    default:
      return ArrayDisplayFormat::kFlat;
  }
}

void Reader::InnerParseNumericProperty(ParsedNode* parent, const Block* block) {
  auto name = GetAndValidateName(ValueBlockFields::NameIndex::Get<size_t>(block->header));
  if (!name.has_value()) {
    return;
  }

  auto* parent_node = parent->hierarchy.node_ptr();

  BlockType type = GetType(block);
  switch (type) {
    case BlockType::kIntValue:
      parent_node->add_property(
          PropertyValue(std::move(name.value()), IntPropertyValue(block->payload.i64)));
      return;
    case BlockType::kUintValue:
      parent_node->add_property(
          PropertyValue(std::move(name.value()), UintPropertyValue(block->payload.u64)));
      return;
    case BlockType::kDoubleValue:
      parent_node->add_property(
          PropertyValue(std::move(name.value()), DoublePropertyValue(block->payload.f64)));
      return;
    case BlockType::kBoolValue:
      parent_node->add_property(
          PropertyValue(std::move(name.value()), BoolPropertyValue(block->payload.u64)));
      return;
    case BlockType::kArrayValue: {
      auto entry_type = ArrayBlockPayload::EntryType::Get<BlockType>(block->payload.u64);
      auto count = ArrayBlockPayload::Count::Get<uint8_t>(block->payload.u64);
      if (GetArraySlot<const int64_t>(block, count - 1) == nullptr) {
        // Block does not store the entire array.
        return;
      }

      auto array_format = ArrayBlockFormatToDisplay(
          ArrayBlockPayload::Flags::Get<ArrayBlockFormat>(block->payload.u64));

      if (entry_type == BlockType::kIntValue) {
        std::vector<int64_t> values;
        std::copy(GetArraySlot<const int64_t>(block, 0), GetArraySlot<const int64_t>(block, count),
                  std::back_inserter(values));
        parent_node->add_property(
            PropertyValue(std::move(name.value()), IntArrayValue(std::move(values), array_format)));
      } else if (entry_type == BlockType::kUintValue) {
        std::vector<uint64_t> values;
        std::copy(GetArraySlot<const uint64_t>(block, 0),
                  GetArraySlot<const uint64_t>(block, count), std::back_inserter(values));
        parent_node->add_property(PropertyValue(std::move(name.value()),
                                                UintArrayValue(std::move(values), array_format)));
      } else if (entry_type == BlockType::kDoubleValue) {
        std::vector<double> values;
        std::copy(GetArraySlot<const double>(block, 0), GetArraySlot<const double>(block, count),
                  std::back_inserter(values));
        parent_node->add_property(PropertyValue(std::move(name.value()),
                                                DoubleArrayValue(std::move(values), array_format)));
      }
      return;
    }
    default:
      return;
  }
}

void Reader::InnerParseProperty(ParsedNode* parent, const Block* block) {
  auto name = GetAndValidateName(ValueBlockFields::NameIndex::Get<size_t>(block->header));
  if (!name.has_value()) {
    return;
  }

  // Do not allow reading more bytes than exist in the buffer for any property. This safeguards
  // against cycles and excessive memory usage.
  size_t remaining_length = std::min(
      snapshot_.size(), PropertyBlockPayload::TotalLength::Get<size_t>(block->payload.u64));
  size_t current_offset = 0;
  std::vector<uint8_t> buf;

  BlockIndex cur_extent = PropertyBlockPayload::ExtentIndex::Get<BlockIndex>(block->payload.u64);
  auto* extent = internal::GetBlock(&snapshot_, cur_extent);
  while (remaining_length > 0) {
    if (!extent || GetType(extent) != BlockType::kExtent) {
      break;
    }
    size_t len = std::min(remaining_length, PayloadCapacity(GetOrder(extent)));
    buf.insert(buf.end(), extent->payload_ptr(), extent->payload_ptr() + len);
    remaining_length -= len;
    current_offset += len;

    BlockIndex next_extent = ExtentBlockFields::NextExtentIndex::Get<BlockIndex>(extent->header);

    extent = internal::GetBlock(&snapshot_, next_extent);
  }

  auto* parent_node = parent->hierarchy.node_ptr();
  if (PropertyBlockPayload::Flags::Get<uint8_t>(block->payload.u64) &
      static_cast<uint8_t>(PropertyBlockFormat::kBinary)) {
    parent_node->add_property(
        inspect::PropertyValue(std::move(name.value()), inspect::ByteVectorPropertyValue(buf)));
  } else {
    parent_node->add_property(
        inspect::PropertyValue(std::move(name.value()),
                               inspect::StringPropertyValue(std::string(buf.begin(), buf.end()))));
  }
}

void Reader::InnerParseLink(ParsedNode* parent, const Block* block) {
  auto name = GetAndValidateName(ValueBlockFields::NameIndex::Get<size_t>(block->header));
  if (name->empty()) {
    return;
  }

  auto content =
      GetAndValidateName(LinkBlockPayload::ContentIndex::Get<size_t>(block->payload.u64));
  if (content->empty()) {
    return;
  }

  LinkDisposition disposition;
  switch (LinkBlockPayload::Flags::Get<LinkBlockDisposition>(block->payload.u64)) {
    case LinkBlockDisposition::kChild:
      disposition = LinkDisposition::kChild;
      break;
    case LinkBlockDisposition::kInline:
      disposition = LinkDisposition::kInline;
      break;
  }

  parent->hierarchy.node_ptr()->add_link(
      LinkValue(std::move(name.value()), std::move(content.value()), disposition));
}

void Reader::InnerCreateObject(BlockIndex index, const Block* block) {
  auto name = GetAndValidateName(ValueBlockFields::NameIndex::Get<BlockIndex>(block->header));
  if (!name.has_value()) {
    return;
  }
  auto* parsed_node = GetOrCreate(index);
  auto parent_index = ValueBlockFields::ParentIndex::Get<BlockIndex>(block->header);
  parsed_node->InitializeNode(std::move(name.value()), parent_index);
  if (parent_index != index) {
    // Only link to a parent if the parent can be valid (not index 0).
    auto* parent = GetOrCreate(parent_index);
    parent->children_count += 1;
  }
}

fit::result<Hierarchy> ReadFromSnapshotTree(const SnapshotTree& tree) {
  auto read_result = internal::Reader(tree.snapshot).Read();
  if (!read_result.is_ok()) {
    return read_result;
  }

  auto ret = read_result.take_value();

  VisitHierarchiesWithLink(&ret, [&](Hierarchy* cur) {
    for (const auto& link : cur->node().links()) {
      auto it = tree.children.find(link.content());
      if (it == tree.children.end()) {
        cur->add_missing_value(MissingValueReason::kLinkNotFound, link.name());
        continue;
      }

      // TODO(crjohns): Remove recursion, or limit depth.
      auto next_result = ReadFromSnapshotTree(it->second);
      if (!next_result.is_ok()) {
        cur->add_missing_value(MissingValueReason::kLinkHierarchyParseFailure, link.name());
        continue;
      }

      if (link.disposition() == LinkDisposition::kChild) {
        // The linked hierarchy is a child of this node, add it to the list of children.
        next_result.value().node_ptr()->set_name(link.name());
        cur->add_child(next_result.take_value());
      } else if (link.disposition() == LinkDisposition::kInline) {
        // The linked hierarchy is meant to have its contents inlined into this node.
        auto next = next_result.take_value();

        // Move properties into this node.
        for (auto& prop : next.node_ptr()->take_properties()) {
          cur->node_ptr()->add_property(std::move(prop));
        }

        // Move children into this node.
        for (auto& child : next.take_children()) {
          cur->add_child(std::move(child));
        }

        // Copy missing values.
        for (const auto& missing : next.missing_values()) {
          cur->add_missing_value(missing.reason, missing.name);
        }

        // There will be no further links that have not already been processed, since we recursively
        // get the hierarchy from a SnapshotTree.
      } else {
        cur->add_missing_value(MissingValueReason::kLinkInvalid, link.name());
      }
    }
  });

  return fit::ok(std::move(ret));
}

}  // namespace internal

fit::result<Hierarchy> ReadFromSnapshot(Snapshot snapshot) {
  internal::Reader reader(std::move(snapshot));
  return reader.Read();
}

fit::result<Hierarchy> ReadFromVmo(const zx::vmo& vmo) {
  inspect::Snapshot snapshot;
  if (inspect::Snapshot::Create(std::move(vmo), &snapshot) != ZX_OK) {
    return fit::error();
  }
  return ReadFromSnapshot(std::move(snapshot));
}

fit::result<Hierarchy> ReadFromBuffer(std::vector<uint8_t> buffer) {
  inspect::Snapshot snapshot;
  if (inspect::Snapshot::Create(std::move(buffer), &snapshot) != ZX_OK) {
    // TODO(CF-865): Best-effort read of invalid snapshots.
    return fit::error();
  }
  return ReadFromSnapshot(std::move(snapshot));
}

fit::promise<Hierarchy> ReadFromInspector(Inspector inspector) {
  return SnapshotTreeFromInspector(std::move(inspector)).and_then(internal::ReadFromSnapshotTree);
}

}  // namespace inspect
