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

#include "src/developer/debug/zxdb/common/string_util.h"
#include "src/developer/debug/zxdb/symbols/function.h"
#include "src/developer/debug/zxdb/symbols/input_location.h"
#include "src/developer/debug/zxdb/symbols/lazy_symbol.h"
#include "src/developer/debug/zxdb/symbols/line_details.h"
#include "src/developer/debug/zxdb/symbols/location.h"
#include "src/developer/debug/zxdb/symbols/test_symbol_module.h"

namespace zxdb {

MockModuleSymbols::MockModuleSymbols(const std::string& local_file_name)
    : local_file_name_(local_file_name) {}
MockModuleSymbols::~MockModuleSymbols() = default;

void MockModuleSymbols::AddSymbolLocations(const Identifier& name, std::vector<Location> locs) {
  named_symbols_[name] = std::move(locs);
}

void MockModuleSymbols::AddSymbolLocations(const std::string& name, std::vector<Location> locs) {
  named_symbols_[TestSymbolModule::SplitName(name)] = std::move(locs);
}

void MockModuleSymbols::AddSymbolLocations(uint64_t address, std::vector<Location> locs) {
  addr_symbols_[address] = std::move(locs);
}

void MockModuleSymbols::AddLineDetails(uint64_t address, LineDetails details) {
  lines_[address] = std::move(details);
}

void MockModuleSymbols::AddSymbolRef(const IndexNode::SymbolRef& die, fxl::RefPtr<Symbol> symbol) {
  die_refs_[die.offset()] = std::move(symbol);
}

void MockModuleSymbols::AddFileName(const std::string& file_name) { files_.push_back(file_name); }

void MockModuleSymbols::AddDebugAddrEntry(uint64_t addr_base, uint64_t index, uint64_t value) {
  debug_addr_entries_[std::make_pair(addr_base, index)] = value;
}

ModuleSymbolStatus MockModuleSymbols::GetStatus() const {
  ModuleSymbolStatus status;
  status.name = local_file_name_;
  status.functions_indexed = named_symbols_.size();
  status.symbols_loaded = true;
  return status;
}

std::vector<Location> MockModuleSymbols::ResolveInputLocation(const SymbolContext& symbol_context,
                                                              const InputLocation& input_location,
                                                              const ResolveOptions& options) const {
  std::vector<Location> result;
  switch (input_location.type) {
    case InputLocation::Type::kAddress:
      if (auto found = addr_symbols_.find(input_location.address); found != addr_symbols_.end()) {
        result = found->second;
      } else {
        // Return identity for all non-found addresses.
        result.emplace_back(Location::State::kAddress, input_location.address);
      }
      break;
    case InputLocation::Type::kName: {
      // The input may be qualified or unqualified globally. Allow either to match an unqualified
      // expected value.
      if (auto found = named_symbols_.find(input_location.name); found != named_symbols_.end()) {
        result = found->second;
      } else if (input_location.name.qualification() == IdentifierQualification::kGlobal) {
        // Try looking up after removing the global qualifier.
        Identifier unqualified = input_location.name;
        unqualified.set_qualification(IdentifierQualification::kRelative);
        if (auto found = named_symbols_.find(unqualified); found != named_symbols_.end())
          result = found->second;
      }
      break;
    }
    default:
      // More complex stuff is not yet supported by this mock.
      break;
  }

  if (!options.symbolize) {
    // The caller did not request symbols so convert each result to an unsymbolized answer. This
    // will match the type of output from the non-mock version.
    for (size_t i = 0; i < result.size(); i++)
      result[i] = Location(Location::State::kAddress, result[i].address());
  }
  return result;
}

fxl::RefPtr<DwarfUnit> MockModuleSymbols::GetDwarfUnit(const SymbolContext& symbol_context,
                                                       uint64_t absolute_address) const {
  return nullptr;
}

LineDetails MockModuleSymbols::LineDetailsForAddress(const SymbolContext& symbol_context,
                                                     uint64_t absolute_address, bool greedy) const {
  // This mock assumes all addresses are absolute so the symbol context is not used.
  auto found = lines_.find(absolute_address);
  if (found == lines_.end())
    return LineDetails();
  return found->second;
}

std::vector<std::string> MockModuleSymbols::FindFileMatches(std::string_view name) const {
  std::vector<std::string> result;
  for (const std::string& cur : files_) {
    std::string with_slash("/");
    with_slash += std::string(name);
    if (cur == name || StringEndsWith(cur, with_slash))
      result.push_back(cur);
  }
  return result;
}

std::vector<fxl::RefPtr<Function>> MockModuleSymbols::GetMainFunctions() const {
  return std::vector<fxl::RefPtr<Function>>();
}

const Index& MockModuleSymbols::GetIndex() const { return index_; }

LazySymbol MockModuleSymbols::IndexSymbolRefToSymbol(const IndexNode::SymbolRef& die_ref) const {
  auto found = die_refs_.find(die_ref.offset());
  if (found == die_refs_.end())
    return LazySymbol();
  return found->second;
}

bool MockModuleSymbols::HasBinary() const { return false; }

std::optional<uint64_t> MockModuleSymbols::GetDebugAddrEntry(uint64_t addr_base,
                                                             uint64_t index) const {
  if (auto found = debug_addr_entries_.find(std::make_pair(addr_base, index));
      found != debug_addr_entries_.end())
    return found->second;
  return std::nullopt;
}

}  // namespace zxdb
