// 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 "src/developer/debug/zxdb/expr/pretty_tree.h"

#include "src/developer/debug/zxdb/expr/format_node.h"
#include "src/developer/debug/zxdb/expr/format_options.h"
#include "src/developer/debug/zxdb/expr/resolve_collection.h"
#include "src/developer/debug/zxdb/symbols/type.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace zxdb {

namespace {

// Fills the given node for a set/map iterator. The "value" is the referenced value. The container
// type will be either "map" or "set" to make the description.
void FillTreeIteratorNode(const char* container_type, FormatNode* node, ErrOrValue value) {
  if (value.has_error())
    return node->SetDescribedError(value.err());

  // Declare it as a pointer with the value as the pointed-to thing.
  node->set_description_kind(FormatNode::kPointer);

  // There isn't a good address to show since the actual pointer is to the tree node and showing
  // the node address in the description looks misleading. But some generic text.
  node->set_description(std::string(container_type) + "::iterator");

  // Make the dereference child node the value.
  auto deref_node = std::make_unique<FormatNode>("*", value.take_value());
  deref_node->set_child_kind(FormatNode::kPointerExpansion);
  node->children().push_back(std::move(deref_node));
}

}  // namespace

// PrettyTreeIterator ------------------------------------------------------------------------------

void PrettyTreeIterator::Format(FormatNode* node, const FormatOptions& options,
                                const fxl::RefPtr<EvalContext>& context,
                                fit::deferred_callback cb) {
  GetIteratorValue(context, node->value(),
                   [weak_node = node->GetWeakPtr(), cb = std::move(cb)](ErrOrValue value) {
                     if (weak_node)
                       FillTreeIteratorNode("std::set", weak_node.get(), std::move(value));
                   });
}

PrettyTreeIterator::EvalFunction PrettyTreeIterator::GetDereferencer() const {
  return [](const fxl::RefPtr<EvalContext>& context, const ExprValue& iter, EvalCallback cb) {
    GetIteratorValue(std::move(context), iter, std::move(cb));
  };
}

void PrettyTreeIterator::GetIteratorValue(const fxl::RefPtr<EvalContext>& context,
                                          const ExprValue& iter, EvalCallback cb) {
  // Evaluate "static_cast<ITER_TYPE::__node_pointer>(iter.__ptr_)->__value_"
  //
  // Unfortunately, there is no way with the implementation to know when an iterator points to
  // "end" other than it's values look fishy.
  //
  // It would be nice to express this solely in terms of expressions if we can figure out how to
  // express "TREE_TYPE" in the above expression.
  EvalExpressionOn(
      context, iter,
      "reinterpret_cast<" + iter.type()->GetFullName() + "::__node_pointer>(__ptr_)->__value_",
      std::move(cb));
}

// PrettyMapIterator -------------------------------------------------------------------------------

void PrettyMapIterator::Format(FormatNode* node, const FormatOptions& options,
                               const fxl::RefPtr<EvalContext>& context, fit::deferred_callback cb) {
  GetIteratorValue(context, node->value(),
                   [weak_node = node->GetWeakPtr(), cb = std::move(cb)](ErrOrValue value) {
                     if (weak_node)
                       FillTreeIteratorNode("std::map", weak_node.get(), std::move(value));
                   });
}

PrettyMapIterator::EvalFunction PrettyMapIterator::GetDereferencer() const {
  return [](const fxl::RefPtr<EvalContext>& context, const ExprValue& iter, EvalCallback cb) {
    GetIteratorValue(std::move(context), iter, std::move(cb));
  };
}

void PrettyMapIterator::GetIteratorValue(const fxl::RefPtr<EvalContext>& context,
                                         const ExprValue& iter, EvalCallback cb) {
  // Evaluate "static_cast<ITER_TYPE::__node_pointer>(iter.__i_.__ptr_)->__value_.__cc"
  // Where ITER_TYPE is actually the type of "iter.__i_".
  ErrOrValue i_value = ResolveNonstaticMember(context, iter, {"__i_"});
  if (i_value.has_error())
    return cb(i_value);

  // See PrettyTreeIterator above.
  EvalExpressionOn(context, i_value.value(),
                   "reinterpret_cast<" + i_value.value().type()->GetFullName() +
                       "::__node_pointer>(__ptr_)->__value_.__cc",
                   std::move(cb));
}

// PrettyTree --------------------------------------------------------------------------------------

// C++ expression that resolves to a set/map size.
#define TREE_SIZE_EXPRESSION "__tree_.__pair3_.__value_"

PrettyTree::PrettyTree(const std::string& container_name)
    : PrettyType({{"size", TREE_SIZE_EXPRESSION}, {"empty", TREE_SIZE_EXPRESSION " == 0"}}),
      container_name_(container_name) {}

void PrettyTree::Format(FormatNode* node, const FormatOptions& options,
                        const fxl::RefPtr<EvalContext>& context, fit::deferred_callback cb) {
  // Actually getting the set contents in our C++ code with our current asynchronous API is
  // prohibitive. When we have a way that walking the tree can be expressed in a synchronous
  // fashion (either by a scripting language or fancier expressions) we can add this ability.
  //
  // For now, just show the size as the description.
  EvalExpressionOn(context, node->value(), TREE_SIZE_EXPRESSION,
                   [container_name = container_name_, weak_node = node->GetWeakPtr(),
                    cb = std::move(cb)](ErrOrValue size_value) mutable {
                     if (!weak_node)
                       return;
                     if (size_value.has_error())
                       return weak_node->SetDescribedError(size_value.err());

                     uint64_t size = 0;
                     if (Err e = size_value.value().PromoteTo64(&size); e.has_error())
                       return weak_node->SetDescribedError(e);

                     weak_node->set_description(
                         fxl::StringPrintf("%s{size = %" PRIu64 "}", container_name.c_str(), size));
                   });
}

}  // namespace zxdb
