// 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_PROCESS_IMPL_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_PROCESS_IMPL_H_

#include <map>
#include <memory>

#include "src/developer/debug/ipc/protocol.h"
#include "src/developer/debug/zxdb/client/process.h"
#include "src/developer/debug/zxdb/symbols/process_symbols.h"
#include "src/lib/fxl/macros.h"
#include "src/lib/fxl/memory/weak_ptr.h"

namespace zxdb {

class BacktraceCache;
class ProcessSymbolDataProvider;
class TargetImpl;
class ThreadImpl;

class ProcessImpl : public Process, public ProcessSymbols::Notifications {
 public:
  ProcessImpl(TargetImpl* target, uint64_t koid, const std::string& name,
              Process::StartType start_type);
  ~ProcessImpl() override;

  ThreadImpl* GetThreadImplFromKoid(uint64_t koid);

  TargetImpl* target() const { return target_; }

  // Process implementation:
  Target* GetTarget() const override;
  uint64_t GetKoid() const override;
  const std::string& GetName() const override;
  ProcessSymbols* GetSymbols() override;
  void GetModules(fit::callback<void(const Err&, std::vector<debug_ipc::Module>)>) override;
  void GetAspace(
      uint64_t address,
      fit::callback<void(const Err&, std::vector<debug_ipc::AddressRegion>)>) const override;
  std::vector<Thread*> GetThreads() const override;
  Thread* GetThreadFromKoid(uint64_t koid) override;
  void SyncThreads(fit::callback<void()> callback) override;
  void Pause(fit::callback<void()> on_paused) override;
  void Continue(bool forward_exceptions) override;
  void ContinueUntil(std::vector<InputLocation> location,
                     fit::callback<void(const Err&)> cb) override;
  void CancelAllThreadControllers() override;
  fxl::RefPtr<SymbolDataProvider> GetSymbolDataProvider() const override;
  void GetTLSHelpers(GetTLSHelpersCallback cb) override;
  void ReadMemory(uint64_t address, uint32_t size,
                  fit::callback<void(const Err&, MemoryDump)> callback) override;
  void WriteMemory(uint64_t address, std::vector<uint8_t> data,
                   fit::callback<void(const Err&)> callback) override;
  void LoadInfoHandleTable(
      fit::callback<void(ErrOr<std::vector<debug_ipc::InfoHandle>> handles)> callback) override;

  // Notifications from the agent that a thread has started or exited.
  void OnThreadStarting(const debug_ipc::ThreadRecord& record, bool resume);
  void OnThreadExiting(const debug_ipc::ThreadRecord& record);

  // Notification that the list of loaded modules may have been updated.
  void OnModules(std::vector<debug_ipc::Module> modules,
                 const std::vector<debug_ipc::ProcessThreadId>& stopped_threads);

  // Returns true if the caller should show the output. False means silence.
  bool HandleIO(const debug_ipc::NotifyIO&);

  // ProcessSymbols::Notifications implementation (public portion):
  void OnSymbolLoadFailure(const Err& err) override;

  // This is used when a breakpoint with automation is received, this stores the extra data that
  // will be used later.
  void SetMemoryBlocks(uint64_t thread_koid, std::vector<debug_ipc::MemoryBlock> memory_blocks) {
    memory_blocks_[thread_koid] = std::move(memory_blocks);
  }

 private:
  enum {
    kUnloaded,
    kLoading,
    kLoaded,
    kFailed,
  } tls_helper_state_ = kUnloaded;

  // Syncs the threads_ list to the new list of threads passed in .
  void UpdateThreads(const std::vector<debug_ipc::ThreadRecord>& new_threads);

  // ProcessSymbols::Notifications implementation:
  void DidLoadModuleSymbols(LoadedModuleSymbols* module) override;
  void WillUnloadModuleSymbols(LoadedModuleSymbols* module) override;

  uint64_t GetElfSymbolAddress(const std::string& symbol, uint64_t* size);

  // Run the given callback as soon as the TLS helpers are loaded. If the TLS helpers failed to
  // load, pass false to the callback.
  void DoWithHelpers(fit::callback<void(bool)> cb);

  // Load the TLS helpers.
  void LoadTLSHelpers();

  // Updates modules with empty names to reflect the name of the process binary. By convention,
  // the dynamic loader will set the main binary to have a blank name.
  void FixupEmptyModuleNames(std::vector<debug_ipc::Module>& modules) const;

  TargetImpl* const target_;  // The target owns |this|.
  const uint64_t koid_;
  std::string name_;

  // Threads indexed by their thread koid.
  std::map<uint64_t, std::unique_ptr<ThreadImpl>> threads_;

  ProcessSymbols symbols_;

  // TLS Helper blobs.
  TLSHelpers tls_helpers_;

  // Queue of tasks waiting for the helper blobs to be loaded.
  std::vector<fit::callback<void(bool)>> helper_waiters_;

  // Lazily-populated.
  mutable fxl::RefPtr<ProcessSymbolDataProvider> symbol_data_provider_;

  fxl::WeakPtrFactory<ProcessImpl> weak_factory_;

  FXL_DISALLOW_COPY_AND_ASSIGN(ProcessImpl);

  std::map<uint64_t, std::vector<debug_ipc::MemoryBlock>> memory_blocks_;
};

}  // namespace zxdb

#endif  // SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_PROCESS_IMPL_H_
