// 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.

#ifndef SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_MOCK_REMOTE_API_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_MOCK_REMOTE_API_H_

#include "src/developer/debug/ipc/protocol.h"
#include "src/developer/debug/shared/mock_memory.h"
#include "src/developer/debug/zxdb/client/remote_api.h"

namespace zxdb {

// A mock for RemoteAPI that saves messages and sends replies.
//
// Not all of the messages are handled here. Only the ones that are needed by the tests that use
// this mock are necessary. The default implementation of RemoteAPI will assert for calls that
// aren't overridden, so if you get one you should implement it here.
class MockRemoteAPI : public RemoteAPI {
 public:
  MockRemoteAPI();
  ~MockRemoteAPI();

  // Resume. By default Resume() counts the number of calls, but many tests also want to opt-in to
  // an implicit MessageLoop exit when this happens so they can continue testing from after the IPC
  // message is sent.
  void set_resume_quits_loop(bool quit) { resume_quits_loop_ = true; }
  int GetAndResetResumeCount();  // Zeroes out internal value.

  // Thread status.
  void set_thread_status_reply(const debug_ipc::ThreadStatusReply& reply) {
    thread_status_reply_ = reply;
  }

  // Breakpoints.
  int breakpoint_add_count() const { return breakpoint_add_count_; }
  int breakpoint_remove_count() const { return breakpoint_remove_count_; }
  const debug_ipc::AddOrChangeBreakpointRequest& last_breakpoint_add() const {
    return last_breakpoint_add_;
  }
  uint64_t last_breakpoint_id() const { return last_breakpoint_add_.breakpoint.id; }
  uint64_t last_breakpoint_address() const {
    if (last_breakpoint_add_.breakpoint.locations.empty())
      return 0;
    return last_breakpoint_add_.breakpoint.locations[0].address;
  }

  // Sets a memory value that will be returned when requested.
  void AddMemory(uint64_t address, std::vector<uint8_t> data);

  // Sets the register reply for a given category.
  void SetRegisterCategory(debug_ipc::RegisterCategory cat, std::vector<debug_ipc::Register> regs);

  const debug_ipc::WriteRegistersRequest& last_write_registers() const {
    return last_write_registers_;
  }

  // Sets pause reply.
  void set_pause_reply(const debug_ipc::PauseReply& reply) { pause_reply_ = reply; }

  // RemoteAPI implementation.
  void Attach(const debug_ipc::AttachRequest& request,
              fit::callback<void(const Err&, debug_ipc::AttachReply)> cb) override;
  void AddOrChangeBreakpoint(
      const debug_ipc::AddOrChangeBreakpointRequest& request,
      fit::callback<void(const Err&, debug_ipc::AddOrChangeBreakpointReply)> cb) override;
  void RemoveBreakpoint(
      const debug_ipc::RemoveBreakpointRequest& request,
      fit::callback<void(const Err&, debug_ipc::RemoveBreakpointReply)> cb) override;
  void ThreadStatus(const debug_ipc::ThreadStatusRequest& request,
                    fit::callback<void(const Err&, debug_ipc::ThreadStatusReply)> cb) override;
  void Pause(const debug_ipc::PauseRequest& request,
             fit::callback<void(const Err&, debug_ipc::PauseReply)> cb) override;
  void Resume(const debug_ipc::ResumeRequest& request,
              fit::callback<void(const Err&, debug_ipc::ResumeReply)> cb) override;
  void ReadMemory(const debug_ipc::ReadMemoryRequest& request,
                  fit::callback<void(const Err&, debug_ipc::ReadMemoryReply)> cb) override;
  void ReadRegisters(const debug_ipc::ReadRegistersRequest& request,
                     fit::callback<void(const Err&, debug_ipc::ReadRegistersReply)> cb) override;
  void WriteRegisters(const debug_ipc::WriteRegistersRequest& request,
                      fit::callback<void(const Err&, debug_ipc::WriteRegistersReply)> cb) override;

  // No-op for now.
  // TODO(donosoc): The client will detect underlying exceptions by analyzing the threads it
  //                receives upon process attaching, so this will be filled then.
  //                Currently we need this to not assert existing tests.
  void Threads(const debug_ipc::ThreadsRequest& request,
               fit::callback<void(const Err&, debug_ipc::ThreadsReply)> cb) override {}

 private:
  debug_ipc::ThreadStatusReply thread_status_reply_;
  debug_ipc::PauseReply pause_reply_;

  std::map<debug_ipc::RegisterCategory, std::vector<debug_ipc::Register>> register_replies_;

  bool resume_quits_loop_ = false;
  int resume_count_ = 0;
  int breakpoint_add_count_ = 0;
  int breakpoint_remove_count_ = 0;
  debug_ipc::AddOrChangeBreakpointRequest last_breakpoint_add_;
  debug_ipc::WriteRegistersRequest last_write_registers_;
  debug_ipc::MockMemory memory_;
};

}  // namespace zxdb

#endif  // SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_MOCK_REMOTE_API_H_
