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

#include <string.h>

#include <memory>

#include "src/developer/debug/debug_agent/mock_exception_handle.h"
#include "src/developer/debug/debug_agent/mock_thread_handle.h"
#include "src/developer/debug/ipc/records.h"

namespace debug_agent {

NativeProcessHandle MockProcessHandle::null_handle_;

MockProcessHandle::MockProcessHandle(zx_koid_t process_koid, std::string name)
    : process_koid_(process_koid), name_(std::move(name)) {
  // 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 MockProcessHandle::AddThreadAndSendEvent(MockThreadHandle thread) {
  auto mock_exception = std::make_unique<MockExceptionHandle>(GetKoid(), thread.GetKoid());
  threads_.push_back(std::move(thread));

  if (observer_) {
    observer_->OnThreadStarting(std::move(mock_exception));
  }
}

std::vector<std::unique_ptr<ThreadHandle>> MockProcessHandle::GetChildThreads() const {
  // Need to return a unique set of objects every time so make copies.
  std::vector<std::unique_ptr<ThreadHandle>> result;
  for (auto& thread : threads_)
    result.push_back(std::make_unique<MockThreadHandle>(thread));
  return result;
}

debug::Status MockProcessHandle::Kill() { return kill_status_; }

int64_t MockProcessHandle::GetReturnCode() const { return 0; }

debug::Status MockProcessHandle::Attach(ProcessHandleObserver* observer, AttachConfig config) {
  if (config.claim_exception_channel) {
    is_attached_ = true;
  }
  observer_ = observer;
  return debug::Status();
}

void MockProcessHandle::Detach() { is_attached_ = false; }

uint64_t MockProcessHandle::GetLoaderBreakpointAddress() {
  // Not currently implemented in this mock.
  return kLoaderBreakpointAddress;
}

std::vector<debug_ipc::AddressRegion> MockProcessHandle::GetAddressSpace(uint64_t address) const {
  // Not currently implemented in this mock.
  return {};
}

std::optional<debug_ipc::AddressRegion> MockProcessHandle::GetSharedAddressSpace() const {
  // Not currently implemented in this mock.
  return std::nullopt;
}

std::vector<debug_ipc::Module> MockProcessHandle::GetModules() const {
  // Not currently implemented in this mock.
  return {};
}

fit::result<debug::Status, std::vector<debug_ipc::InfoHandle>> MockProcessHandle::GetHandles()
    const {
  // Not currently implemented in this mock.
  return fit::success(std::vector<debug_ipc::InfoHandle>());
}

debug::Status MockProcessHandle::ReadMemory(uintptr_t address, void* buffer, size_t len,
                                            size_t* actual) const {
  auto vect = mock_memory_.ReadMemory(address, len);
  if (!vect.empty())
    memcpy(buffer, vect.data(), vect.size());
  *actual = vect.size();
  return debug::Status();
}

debug::Status MockProcessHandle::WriteMemory(uintptr_t address, const void* buffer, size_t len,
                                             size_t* actual) {
  // This updates the underlying memory object to account for the change. Otherwise some tests
  // become much more complex because they have to manually manage the memory expected by the
  // code under test.
  //
  // The MockMemory object isn't necessarily designed for this and there will be some limitations.
  // Calling AddMemory adds that span to the mapped memory, but does not necessarily combine it with
  // other spans. If a larger region of memory is requested, the results may be invalid, but if the
  // same sized block is always read and written, it will be fine. Since our main test use is for
  // writing breakpoints which always use fixed sizes, this works fine for now. If this limitation
  // is a problem, we should enhance MockMemory.
  const uint8_t* src = static_cast<const uint8_t*>(buffer);
  mock_memory_.AddMemory(address, std::vector<uint8_t>(src, src + len));

  memory_writes_.emplace_back(address, std::vector<uint8_t>(src, &src[len]));
  return debug::Status();
}

std::vector<debug_ipc::MemoryBlock> MockProcessHandle::ReadMemoryBlocks(uint64_t address,
                                                                        uint32_t size) const {
  auto mem_vect = mock_memory_.ReadMemory(address, size);
  debug_ipc::MemoryBlock mem_block;
  mem_block.data = std::move(mem_vect);
  mem_block.size = size;
  mem_block.valid = true;
  mem_block.address = address;
  std::vector<debug_ipc::MemoryBlock> mem_blocks;
  mem_blocks.emplace_back(std::move(mem_block));
  return mem_blocks;
}

debug::Status MockProcessHandle::SaveMinidump(const std::vector<DebuggedThread*>& threads,
                                              std::vector<uint8_t>* core_data) {
  // Not currently implemented.
  return debug::Status();
}

}  // namespace debug_agent
