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

#pragma once

#include <stddef.h>
#include <stdint.h>

#include <functional>
#include <string>

#include "garnet/bin/zxdb/client/client_object.h"
#include "garnet/bin/zxdb/client/frame_fingerprint.h"
#include "garnet/bin/zxdb/client/setting_store.h"
#include "garnet/bin/zxdb/client/thread_observer.h"
#include "garnet/lib/debug_ipc/protocol.h"
#include "lib/fxl/macros.h"
#include "lib/fxl/memory/weak_ptr.h"
#include "lib/fxl/observer_list.h"

namespace zxdb {

class Err;
class Frame;
class Process;
class RegisterSet;
class ThreadController;

// The flow control commands on this object (Pause, Continue, Step...) apply
// only to this thread (other threads will continue to run or not run
// as they were previously).
class Thread : public ClientObject {
 public:
  explicit Thread(Session* session);
  ~Thread() override;

  void AddObserver(ThreadObserver* observer);
  void RemoveObserver(ThreadObserver* observer);

  fxl::WeakPtr<Thread> GetWeakPtr();

  // Guaranteed non-null.
  virtual Process* GetProcess() const = 0;

  virtual uint64_t GetKoid() const = 0;
  virtual const std::string& GetName() const = 0;

  // The state of the thread isn't necessarily up-to-date. There are no
  // system messages for a thread transitioning to suspended, for example.
  // To make sure this is up-to-date, call Process::SyncThreads() or
  // Thread::SyncFrames().
  virtual debug_ipc::ThreadRecord::State GetState() const = 0;
  virtual debug_ipc::ThreadRecord::BlockedReason GetBlockedReason() const = 0;

  virtual void Pause() = 0;
  virtual void Continue() = 0;

  // Continues the thread using the given ThreadController. This is used
  // to implement the more complex forms of stepping.
  //
  // The on_continue callback does NOT indicate that the thread stopped again.
  // This is because many thread controllers may need to do asynchronous setup
  // that could fail. It is issued when the thread is actually resumed or when
  // the resumption fails.
  //
  // The on_continue callback may be issued reentrantly from within the stack
  // of the ContinueWith call if the controller was ready synchronously.
  //
  // On failure the ThreadController will be removed and the thread will not
  // be continued.
  virtual void ContinueWith(std::unique_ptr<ThreadController> controller,
                            std::function<void(const Err&)> on_continue) = 0;

  // Notification from a ThreadController that it has completed its job. The
  // thread controller should be removed from this thread and deleted.
  virtual void NotifyControllerDone(ThreadController* controller) = 0;

  virtual void StepInstruction() = 0;

  // Access to the stack frames for this thread at its current suspended
  // or blocked-in-exception position. If a thread is running, blocked (not in
  // an exception), or in any other state, the stack frames are not available.
  //
  // When a thread is suspended or blocked in an exception, it will have its
  // 0th frame available (the current IP and stack position) and the 1st (the
  // calling frame) if possible. So such threads will always have at least one
  // result in the vector returned by GetFrames(), and normally two.
  //
  // If the full backtrace is needed, SyncFrames() can be called which will
  // compute the full backtrace and issue the callback when complete. This
  // backtrace will be cached until the thread is resumed. It has the side
  // effect of updating other thread status information.
  //
  // HasAllFrames() will return true if the full backtrace is currently
  // available (= true) or if only the current position is available (= false).
  //
  // Since the state of a thread isn't available synchronously in a non-racy
  // manner, you can always request a Sync of the frames if the frames are not
  // all available. If the thread is destroyed before the backtrace can be
  // issued, the callback will not be executed.
  //
  // If the thread is running when the request is processed, the callback will
  // be issued but a subsequent call to GetFrames() will return an empty vector
  // and HasAllFrames() will return false. This call can race with other
  // requests to resume a thread, so you can't make any assumptions about the
  // availability of the stack from the callback.
  //
  // The pointers in the vector returned by GetFrames() can be cached if the
  // code listens for ThreadObserver::OnThreadFramesInvalidated() and clears
  // the cache at that point.
  virtual const std::vector<Frame*>& GetFrames() const = 0;
  virtual bool HasAllFrames() const = 0;
  virtual void SyncFrames(std::function<void()> callback) = 0;

  // Computes the stack frame fingerprint for the stack frame at the given
  // index. This function requires that that the previous stack frame
  // (frame_index + 1) by present since the stack base is the SP of the
  // calling function.
  //
  // This function can always return the fingerprint for frame 0. Other
  // frames requires HasAllFrames() == true or it will assert.
  //
  // See frame.h for a discussion on stack frames.
  virtual FrameFingerprint GetFrameFingerprint(size_t frame_index) const = 0;

  // Obtains the state of the registers for a particular thread.
  // The thread must be stopped in order to get the values.
  //
  // The returned structures are architecture independent, but the contents
  // will be dependent on the architecture the target is running on.
  virtual void GetRegisters(
      std::vector<debug_ipc::RegisterCategory::Type> cats_to_get,
      std::function<void(const Err&, const RegisterSet&)>) = 0;

  // Provides the setting schema for this object.
  static fxl::RefPtr<SettingSchema> GetSchema();

  SettingStore& settings() { return settings_; }

 protected:
  fxl::ObserverList<ThreadObserver>& observers() { return observers_; }

  SettingStore settings_;

 private:
  fxl::ObserverList<ThreadObserver> observers_;
  fxl::WeakPtrFactory<Thread> weak_factory_;

  FXL_DISALLOW_COPY_AND_ASSIGN(Thread);
};

}  // namespace zxdb
