// 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/symbols/index_node.h"

#include <lib/syslog/cpp/macros.h>

#include <sstream>

#include "src/developer/debug/zxdb/symbols/dwarf_symbol_factory.h"
#include "src/developer/debug/zxdb/symbols/function.h"

namespace zxdb {

namespace {

void DumpMap(const IndexNode::Map& map, int indent, const char* heading,
             DwarfSymbolFactory* factory_for_loc, std::ostream& out) {
  if (map.empty())
    return;

  out << std::string(indent * 2, ' ') << heading << std::endl;
  for (const auto& cur : map)
    cur.second.Dump(cur.first, out, factory_for_loc, indent + 1);
}

}  // namespace

IndexNode* IndexNode::AddChild(Kind kind, const char* name) {
  FX_DCHECK(name);

  // TODO(brettw) Get some kind of transparent lookup here to avoid making an intermediate
  // std::string.
  Map& map = MapForKind(kind);
  auto found = map.find(name);
  if (found == map.end()) {
    found = map.emplace(std::piecewise_construct, std::forward_as_tuple(name),
                        std::forward_as_tuple(kind))
                .first;
  }

  return &found->second;
}

IndexNode* IndexNode::AddChild(Kind kind, const char* name, const SymbolRef& ref) {
  auto added = AddChild(kind, name);
  added->AddDie(ref);
  return added;
}

void IndexNode::AddDie(const SymbolRef& ref) {
  switch (kind_) {
    case Kind::kNone:
    case Kind::kRoot:
      FX_NOTREACHED() << "Should not try to add a none or root DIE.";
      return;
    case Kind::kNamespace:
      // Don't bother saving namespaces.
      return;
    case Kind::kType:
      // A type can only have one entry. If it's a forward declaration, we'll promote it to a
      // definition. But otherwise won't append.
      if (!dies_.empty()) {
        if (!dies_[0].is_declaration())
          return;  // Existing one is already a definition, never need another.
        else if (ref.is_declaration())
          return;       // Both existing one and new one are definitions, don't need to upgrade.
        dies_.clear();  // Update existing one by removing, will be appended below.
      }
      break;
    case Kind::kFunction:
    case Kind::kVar:
      break;  // Always store these kinds.
  }

  dies_.push_back(ref);
}

const IndexNode::Map& IndexNode::MapForKind(Kind kind) const {
  FX_DCHECK(static_cast<int>(kind) >= 0 &&
            static_cast<int>(kind) < static_cast<int>(Kind::kEndPhysical));
  return children_[static_cast<int>(kind)];
}

IndexNode::Map& IndexNode::MapForKind(Kind kind) {
  FX_DCHECK(static_cast<int>(kind) >= 0 &&
            static_cast<int>(kind) < static_cast<int>(Kind::kEndPhysical));
  return children_[static_cast<int>(kind)];
}

std::string IndexNode::AsString(int indent_level) const {
  std::ostringstream out;
  Dump(out, nullptr, indent_level);
  return out.str();
}

void IndexNode::Dump(std::ostream& out, DwarfSymbolFactory* factory_for_loc,
                     int indent_level) const {
  DumpMap(namespaces(), indent_level + 1, "Namespaces:", factory_for_loc, out);
  DumpMap(types(), indent_level + 1, "Types:", factory_for_loc, out);
  DumpMap(functions(), indent_level + 1, "Functions:", factory_for_loc, out);
  DumpMap(vars(), indent_level + 1, "Variables:", factory_for_loc, out);
}

void IndexNode::Dump(const std::string& name, std::ostream& out,
                     DwarfSymbolFactory* factory_for_loc, int indent_level) const {
  out << std::string(indent_level * 2, ' ');
  if (name.empty())
    out << "<<empty index string>>";
  else
    out << name;

  if (factory_for_loc) {
    // Dump location information too.
    const char* separator = ": ";
    for (const SymbolRef& die_ref : dies_) {
      out << separator;
      separator = ", ";

      LazySymbol lazy = factory_for_loc->MakeLazy(die_ref.offset());
      const Symbol* symbol = lazy.Get();
      if (const Function* function = symbol->As<Function>()) {
        out << function->code_ranges().ToString();
      } else {
        // Everything else just gets the DIE offset so we can identify it. This can be customized
        // in the future if needed.
        out << std::hex << "0x" << die_ref.offset();
      }
    }
  }

  out << std::endl;
  Dump(out, factory_for_loc, indent_level);
}

}  // namespace zxdb
