// Copyright 2018 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/symbol_utils.h"

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

#include "src/developer/debug/shared/logging/logging.h"
#include "src/developer/debug/zxdb/symbols/array_type.h"
#include "src/developer/debug/zxdb/symbols/base_type.h"
#include "src/developer/debug/zxdb/symbols/collection.h"
#include "src/developer/debug/zxdb/symbols/compile_unit.h"
#include "src/developer/debug/zxdb/symbols/data_member.h"
#include "src/developer/debug/zxdb/symbols/dwarf_tag.h"
#include "src/developer/debug/zxdb/symbols/modified_type.h"
#include "src/developer/debug/zxdb/symbols/namespace.h"
#include "src/developer/debug/zxdb/symbols/template_parameter.h"
#include "src/developer/debug/zxdb/symbols/type.h"
#include "src/developer/debug/zxdb/symbols/variable.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace zxdb {

namespace {

// Since we can't use the expression system to resolve the actual value from
// DW_TAG_template_value_parameters, we have to do a simple decoding ourselves.
void AddTemplateValueToName(std::string& name, const TemplateParameter* template_value) {
  auto base_type = template_value->type().Get()->As<Type>()->StripCVT()->As<BaseType>();

  if (!base_type)
    return;

  // This vector assumes little endian, so it's in LSB -> MSB order.
  std::vector<uint8_t> v = template_value->const_value().GetConstValue(base_type->byte_size());
  std::string s;

  switch (base_type->base_type()) {
    case BaseType::kBaseTypeBoolean: {
      FX_DCHECK(v.size() == 1);
      if (v[0] == 1) {
        s = "true";
      } else {
        s = "false";
      }
      break;
    }
    case BaseType::kBaseTypeSignedChar:
    case BaseType::kBaseTypeUnsignedChar: {
      FX_DCHECK(v.size() == 1);
      s = fxl::StringPrintf("'%c'", static_cast<char>(v[0]));
      break;
    }
    case BaseType::kBaseTypeSigned:
    case BaseType::kBaseTypeUnsigned: {
      FX_DCHECK(v.size() >= 2);
      uint64_t t = 0;
      for (int i = base_type->byte_size() - 1; i >= 0; i--) {
        t |= (static_cast<uint64_t>(v[i]) << (8 * i));
      }
      s = std::to_string(t);
      break;
    }
    default:
      LOGS(Warn) << BaseType::BaseTypeToString(base_type->base_type(), true)
                 << " is not supported.";
      return;
  }

  AddTemplateParameterToName(name, s.c_str());
}
}  // namespace

Identifier GetSymbolScopePrefix(const Symbol* symbol) {
  if (!symbol->parent().is_valid())
    return Identifier(IdentifierQualification::kGlobal);  // No prefix

  fxl::RefPtr<Symbol> parent = symbol->parent().Get();
  if (parent->tag() == DwarfTag::kCompileUnit)
    return Identifier(IdentifierQualification::kGlobal);  // Don't go above compilation units.

  if (parent->As<Namespace>() || parent->As<Collection>() || parent->As<Function>()) {
    // These are the types that get qualified.
    return parent->GetIdentifier();
  }
  // Anything else is skipped and we just return the parent's prefix. This
  // will include things like lexical blocks.
  return GetSymbolScopePrefix(parent.get());
}

fxl::RefPtr<Collection> MakeRustTuple(const std::string& name,
                                      const std::vector<fxl::RefPtr<Type>>& members) {
  auto coll = fxl::MakeRefCounted<Collection>(DwarfTag::kStructureType, name);
  auto unit =
      fxl::MakeRefCounted<CompileUnit>(DwarfTag::kCompileUnit, fxl::WeakPtr<ModuleSymbols>(),
                                       nullptr, DwarfLang::kRust, "<no file>", std::nullopt);
  coll->set_parent(UncachedLazySymbol::MakeUnsafe(unit));

  uint32_t offset = 0;
  std::vector<LazySymbol> data_members;
  for (size_t i = 0; i < members.size(); i++) {
    auto& type = members[i];
    auto data = fxl::MakeRefCounted<DataMember>("__" + std::to_string(i), type, offset);

    data_members.emplace_back(std::move(data));
    offset += type->byte_size();
  }

  coll->set_byte_size(offset);
  coll->set_data_members(std::move(data_members));
  return coll;
}

fxl::RefPtr<Type> MakeStringLiteralType(size_t length) {
  auto char_type = fxl::MakeRefCounted<BaseType>(BaseType::kBaseTypeSignedChar, 1, "char");
  return fxl::MakeRefCounted<ArrayType>(std::move(char_type), length);
}

fxl::RefPtr<Type> AddCVQualifiersToMatch(const Type* reference, fxl::RefPtr<Type> modified) {
  const Type* source = reference;
  while (source) {
    const ModifiedType* mod_source = source->As<ModifiedType>();
    if (!mod_source || !DwarfTagIsCVQualifier(mod_source->tag()))
      break;

    modified = fxl::MakeRefCounted<ModifiedType>(mod_source->tag(), std::move(modified));
    source = mod_source->modified().Get()->As<Type>();
  }

  return modified;
}

bool NameHasTemplate(std::string_view name) { return !name.empty() && name.back() == '>'; }

void AddTemplateParameterToName(std::string& original, const char* type_name) {
  if (!type_name)
    return;

  // This type already has a template type, we need to append this one.
  if (NameHasTemplate(original)) {
    original.pop_back();
    std::string append_str = ", ";
    append_str += type_name;
    original.append(append_str);
  } else {
    // No template type yet, add "<...>".
    original.push_back('<');
    original.append(type_name);
  }

  original.push_back('>');
}

void AddAllTemplateParametersToName(std::string& name,
                                    const std::vector<LazySymbol>& template_params) {
  for (const auto& param : template_params) {
    const TemplateParameter* template_parameter = param.Get()->As<TemplateParameter>();
    if (template_parameter) {
      if (template_parameter->is_value() && template_parameter->const_value().has_value()) {
        AddTemplateValueToName(name, template_parameter);
      } else {
        AddTemplateParameterToName(
            name, template_parameter->type().Get()->As<Type>()->GetAssignedName().c_str());
      }
    }
  }
}

}  // namespace zxdb
