// Copyright 2020 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/debug_agent/mock_thread_handle.h"

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

#include "src/developer/debug/debug_agent/mock_suspend_handle.h"

namespace debug_agent {

zx::thread MockThreadHandle::null_handle_;

MockThreadHandle::MockThreadHandle(zx_koid_t thread_koid, std::string name)
    : thread_koid_(thread_koid), name_(std::move(name)), suspend_count_(std::make_shared<int>(0)) {
  // Tests could accidentally write to this handle since it's returned as a mutable value in some
  // cases. Catch accidents like that.
  FX_DCHECK(!null_handle_);
}

void MockThreadHandle::SetRegisterCategory(debug::RegisterCategory cat,
                                           std::vector<debug::RegisterValue> values) {
  FX_CHECK(static_cast<size_t>(cat) < std::size(registers_));
  registers_[static_cast<size_t>(cat)] = std::move(values);
}

size_t MockThreadHandle::BreakpointInstallCount(uint64_t address) const {
  auto it = bp_installs_.find(address);
  if (it == bp_installs_.end())
    return 0;
  return it->second;
}

size_t MockThreadHandle::TotalBreakpointInstallCalls() const {
  int total = 0;
  for (auto it : bp_installs_)
    total += it.second;
  return total;
}

size_t MockThreadHandle::BreakpointUninstallCount(uint64_t address) const {
  auto it = bp_uninstalls_.find(address);
  if (it == bp_uninstalls_.end())
    return 0;
  return it->second;
}

size_t MockThreadHandle::TotalBreakpointUninstallCalls() const {
  int total = 0;
  for (auto it : bp_uninstalls_)
    total += it.second;
  return total;
}

size_t MockThreadHandle::WatchpointInstallCount(const debug::AddressRange& range) const {
  auto it = wp_installs_.find(range);
  if (it == wp_installs_.end())
    return 0;
  return it->second;
}

size_t MockThreadHandle::TotalWatchpointInstallCalls() const {
  int total = 0;
  for (auto it : wp_installs_)
    total += it.second;
  return total;
}

size_t MockThreadHandle::WatchpointUninstallCount(const debug::AddressRange& range) const {
  auto it = wp_uninstalls_.find(range);
  if (it == wp_uninstalls_.end())
    return 0;
  return it->second;
}

size_t MockThreadHandle::TotalWatchpointUninstallCalls() const {
  int total = 0;
  for (auto it : wp_uninstalls_)
    total += it.second;
  return total;
}

debug_ipc::ThreadRecord MockThreadHandle::GetThreadRecord(zx_koid_t process_koid) const {
  debug_ipc::ThreadRecord record;
  record.id = {.process = process_koid, .thread = thread_koid_};
  record.name = "test thread";
  record.state = state_.state;
  record.blocked_reason = state_.blocked_reason;
  return record;
}

debug_ipc::ExceptionRecord MockThreadHandle::GetExceptionRecord() const {
  // Currently not implemented by this mock.
  return debug_ipc::ExceptionRecord();
}

std::unique_ptr<SuspendHandle> MockThreadHandle::Suspend() {
  return std::make_unique<MockSuspendHandle>(suspend_count_);
}

bool MockThreadHandle::WaitForSuspension(TickTimePoint deadline) const { return true; }

std::optional<GeneralRegisters> MockThreadHandle::GetGeneralRegisters() const {
  return general_registers_;
}

void MockThreadHandle::SetGeneralRegisters(const GeneralRegisters& regs) {
  general_registers_ = regs;
}

std::optional<DebugRegisters> MockThreadHandle::GetDebugRegisters() const {
  return debug_registers_;
}

bool MockThreadHandle::SetDebugRegisters(const DebugRegisters& regs) {
  debug_registers_ = regs;
  return true;
}

void MockThreadHandle::SetSingleStep(bool single_step) { single_step_ = single_step; }

std::vector<debug::RegisterValue> MockThreadHandle::ReadRegisters(
    const std::vector<debug::RegisterCategory>& cats_to_get) const {
  std::vector<debug::RegisterValue> result;
  for (const auto cat : cats_to_get) {
    FX_CHECK(static_cast<size_t>(cat) < std::size(registers_));

    const auto& source = registers_[static_cast<size_t>(cat)];
    result.insert(result.end(), source.begin(), source.end());
  }

  return result;
}

std::vector<debug::RegisterValue> MockThreadHandle::WriteRegisters(
    const std::vector<debug::RegisterValue>& regs) {
  // Return the same values as the input to pretend the write succeeded.
  return regs;
}

bool MockThreadHandle::InstallHWBreakpoint(uint64_t address) {
  bp_installs_[address]++;
  return true;
}

bool MockThreadHandle::UninstallHWBreakpoint(uint64_t address) {
  bp_uninstalls_[address]++;
  return true;
}

std::optional<WatchpointInfo> MockThreadHandle::InstallWatchpoint(
    debug_ipc::BreakpointType type, const debug::AddressRange& range) {
  watchpoint_installs_.push_back(WatchpointInstallation{.type = type, .address_range = range});

  wp_installs_[range]++;
  return WatchpointInfo(watchpoint_range_to_return_, watchpoint_slot_to_return_);
}

bool MockThreadHandle::UninstallWatchpoint(const debug::AddressRange& range) {
  wp_uninstalls_[range]++;
  return true;
}

}  // namespace debug_agent
