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

#include "src/developer/debug/zxdb/client/session.h"
#include "src/developer/debug/zxdb/client/setting_schema_definition.h"
#include "src/developer/debug/zxdb/client/system.h"
#include "src/developer/debug/zxdb/common/string_util.h"
#include "src/developer/debug/zxdb/console/string_util.h"
#include "src/developer/debug/zxdb/symbols/elf_symbol.h"
#include "src/developer/debug/zxdb/symbols/function.h"
#include "src/developer/debug/zxdb/symbols/location.h"
#include "src/developer/debug/zxdb/symbols/target_symbols.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace zxdb {

FormatLocationOptions::FormatLocationOptions(const Target* target) : FormatLocationOptions() {
  if (target) {
    show_file_path =
        target->session()->system().settings().GetBool(ClientSettings::System::kShowFilePaths);
    target_symbols = target->GetSymbols();
  }
}

OutputBuffer FormatLocation(const Location& loc, const FormatLocationOptions& opts) {
  if (!loc.is_valid())
    return OutputBuffer("<invalid address>");
  if (!loc.has_symbols())
    return OutputBuffer(fxl::StringPrintf("0x%" PRIx64, loc.address()));

  OutputBuffer result;
  if (opts.always_show_addresses) {
    result = OutputBuffer(Syntax::kComment, fxl::StringPrintf("0x%" PRIx64 ", ", loc.address()));
  }

  bool show_file_line = opts.show_file_line && loc.file_line().is_valid();

  const Symbol* symbol = loc.symbol().Get();
  if (const Function* func = symbol->AsFunction()) {
    // Regular function.
    OutputBuffer func_output = FormatFunctionName(func, opts.func);
    if (!func_output.empty()) {
      result.Append(std::move(func_output));
      if (show_file_line) {
        // Separator between function and file/line.
        result.Append(" " + GetBullet() + " ");
      } else {
        // Check if the address is inside a function and show the offset.
        AddressRange function_range = func->GetFullRange(loc.symbol_context());
        if (function_range.InRange(loc.address())) {
          // Inside a function but no file/line known. Show the offset.
          uint64_t offset = loc.address() - function_range.begin();
          if (offset)
            result.Append(fxl::StringPrintf(" + 0x%" PRIx64, offset));
          if (opts.show_file_line)
            result.Append(Syntax::kComment, " (no line info)");
        }
      }
    }
  } else if (const ElfSymbol* elf_symbol = symbol->AsElfSymbol()) {
    // ELF symbol.
    FormatIdentifierOptions opts;
    opts.show_global_qual = false;
    opts.bold_last = true;
    result.Append(FormatIdentifier(symbol->GetIdentifier(), opts));

    // The address might not be at the beginning of the symbol.
    if (uint64_t offset =
            loc.address() - loc.symbol_context().RelativeToAbsolute(elf_symbol->relative_address()))
      result.Append(fxl::StringPrintf(" + 0x%" PRIx64, offset));
  } else {
    // All other symbol types. This case must handle all other symbol types, some of which might
    // not have identifiers.
    bool printed_name = false;
    if (!symbol->GetIdentifier().empty()) {
      FormatIdentifierOptions opts;
      opts.show_global_qual = false;
      opts.bold_last = true;
      result.Append(FormatIdentifier(symbol->GetIdentifier(), opts));
      printed_name = true;
    } else if (!symbol->GetFullName().empty()) {
      // Fall back on the name.
      result.Append(symbol->GetFullName());
      printed_name = true;
    } else if (!opts.always_show_addresses) {
      // Unnamed symbol, use the address (unless it was printed above already).
      result.Append(to_hex_string(loc.address()));
      printed_name = true;
    }

    // Separator between function and file/line.
    if (printed_name && show_file_line)
      result.Append(" " + GetBullet() + " ");
  }

  if (show_file_line) {
    // Showing the file path means not passing the target symbols because the target symbols is
    // used to shorten the paths.
    result.Append(
        DescribeFileLine(opts.show_file_path ? nullptr : opts.target_symbols, loc.file_line()));
  }
  return result;
}

std::string DescribeFileLine(const TargetSymbols* optional_target_symbols,
                             const FileLine& file_line) {
  std::string result;

  // Name.
  if (file_line.file().empty()) {
    result = "?";
  } else if (!optional_target_symbols) {
    result = file_line.file();
  } else {
    result = optional_target_symbols->GetShortestUniqueFileName(file_line.file());
  }

  result.push_back(':');

  // Line.
  if (file_line.line() == 0)
    result.push_back('?');
  else
    result.append(std::to_string(file_line.line()));

  return result;
}

}  // namespace zxdb
