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

#include "src/developer/debug/shared/message_loop.h"
#include "src/developer/debug/zxdb/client/arch_info.h"
#include "src/developer/debug/zxdb/client/session.h"
#include "src/developer/debug/zxdb/expr/eval_context_impl.h"
#include "src/developer/debug/zxdb/symbols/function.h"
#include "src/developer/debug/zxdb/symbols/mock_symbol_data_provider.h"

namespace zxdb {

namespace {

Location MakeLocation(TargetPointer ip, const std::string& func_name, FileLine file_line) {
  // The function name currently can't handle "::". Because we pass the string to set_assigned_name,
  // they will be treated as literals and not scope separators. If support for those is needed,
  // we need to make the hierarchy of namespaces, etc. to put the function in.
  FX_DCHECK(func_name.find("::") == std::string::npos);

  auto function = fxl::MakeRefCounted<Function>(DwarfTag::kSubprogram);
  function->set_assigned_name(func_name);

  return Location(ip, std::move(file_line), 0, SymbolContext::ForRelativeAddresses(), function);
}

}  // namespace

MockFrame::MockFrame(Session* session, Thread* thread, const Location& location, uint64_t sp,
                     uint64_t cfa, std::vector<debug::RegisterValue> regs, uint64_t frame_base,
                     const Frame* physical_frame, bool is_ambiguous_inline)
    : Frame(session),
      thread_(thread),
      sp_(sp),
      cfa_(cfa),
      general_registers_(std::move(regs)),
      frame_base_(frame_base),
      physical_frame_(physical_frame),
      location_(location),
      is_ambiguous_inline_(is_ambiguous_inline) {}

MockFrame::MockFrame(Session* session, Thread* thread, TargetPointer ip, TargetPointer sp,
                     const std::string& func_name, FileLine file_line)
    : MockFrame(session, thread, MakeLocation(ip, func_name, std::move(file_line)), sp) {}

MockFrame::~MockFrame() = default;

void MockFrame::SetAddress(uint64_t address) {
  location_ = Location(address, location_.file_line(), location_.column(),
                       location_.symbol_context(), location_.symbol());
}

void MockFrame::SetFileLine(const FileLine& file_line) {
  location_ = Location(location_.address(), file_line, location_.column(),
                       location_.symbol_context(), location_.symbol());
}

MockSymbolDataProvider* MockFrame::GetMockSymbolDataProvider() {
  GetSymbolDataProvider();  // Force creation.
  return symbol_data_provider_.get();
}

Thread* MockFrame::GetThread() const { return thread_; }

bool MockFrame::IsInline() const { return !!physical_frame_; }

const Frame* MockFrame::GetPhysicalFrame() const {
  if (physical_frame_)
    return physical_frame_;
  return this;
}

const Location& MockFrame::GetLocation() const { return location_; }
uint64_t MockFrame::GetAddress() const { return location_.address(); }

const std::vector<debug::RegisterValue>* MockFrame::GetRegisterCategorySync(
    debug::RegisterCategory category) const {
  if (category == debug::RegisterCategory::kGeneral)
    return &general_registers_;
  return nullptr;
}

void MockFrame::GetRegisterCategoryAsync(
    debug::RegisterCategory category, bool always_request,
    fit::function<void(const Err&, const std::vector<debug::RegisterValue>&)> cb) {
  Err err;
  std::vector<debug::RegisterValue> regs;
  if (category == debug::RegisterCategory::kGeneral)
    regs = general_registers_;
  else
    err = Err("Register category unavailable from mock.");

  debug::MessageLoop::Current()->PostTask(
      FROM_HERE, [err, regs, cb = std::move(cb)]() mutable { cb(err, regs); });
}

void MockFrame::WriteRegister(debug::RegisterID id, std::vector<uint8_t> data,
                              fit::callback<void(const Err&)> cb) {
  debug::MessageLoop::Current()->PostTask(FROM_HERE, [cb = std::move(cb)]() mutable {
    cb(Err("Writing registers not (yet) supported by the mock."));
  });
}

std::optional<uint64_t> MockFrame::GetBasePointer() const { return frame_base_; }

void MockFrame::GetBasePointerAsync(fit::callback<void(uint64_t)> cb) {
  debug::MessageLoop::Current()->PostTask(
      FROM_HERE, [bp = frame_base_, cb = std::move(cb)]() mutable { cb(bp); });
}

uint64_t MockFrame::GetStackPointer() const { return sp_; }

uint64_t MockFrame::GetCanonicalFrameAddress() const { return cfa_; }

fxl::RefPtr<SymbolDataProvider> MockFrame::GetSymbolDataProvider() const {
  if (!symbol_data_provider_)
    symbol_data_provider_ = fxl::MakeRefCounted<MockSymbolDataProvider>();
  return symbol_data_provider_;
}

fxl::RefPtr<EvalContext> MockFrame::GetEvalContext() const {
  if (!eval_context_) {
    eval_context_ = fxl::MakeRefCounted<EvalContextImpl>(session()->arch_info().abi(),
                                                         fxl::WeakPtr<const ProcessSymbols>(),
                                                         GetSymbolDataProvider(), location_);
  }
  return eval_context_;
}

bool MockFrame::IsAmbiguousInlineLocation() const { return is_ambiguous_inline_; }

}  // namespace zxdb
