// 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_JOB_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_JOB_H_

#include "lib/fit/function.h"
#include "src/developer/debug/ipc/protocol.h"
#include "src/developer/debug/zxdb/client/client_object.h"
#include "src/developer/debug/zxdb/client/filter_observer.h"
#include "src/lib/fxl/macros.h"
#include "src/lib/fxl/memory/weak_ptr.h"

namespace zxdb {

class Err;

// A Job represents the abstract idea of a job that can be debugged.
// The job is attached if there's a corresponding job running and we have the koid and name for it.
class Job : public ClientObject, public FilterObserver {
 public:
  // Note that the callback will be issued in all cases which may be after the job is
  // destroyed. In this case the weak pointer will be null.
  using Callback = fit::callback<void(fxl::WeakPtr<Job> job, const Err&)>;

  enum class State {
    // There is no job currently running. From here, it can only transition to starting.
    kNone,

    // A pending state during the time we requested to be attached and when the reply from the
    // debug_agent comes back.
    kAttaching,

    // The job is attached. From here, it can only transition to none.
    kAttached
  };

  Job(Session* session, bool is_implicit_root);
  ~Job() override;
  fxl::WeakPtr<Job> GetWeakPtr();

  // The implicit root job is one created automatically on startup that's implicitly attached. This
  // job will be automatically reconnected if the connect is reconnected.
  //
  // If the job is explicitly detached, this flag will be cleared (because the user is taking
  // responsibility for where it's attached).
  bool is_implicit_root() const { return is_implicit_root_; }

  // Returns the current job state.
  State state() const { return state_; }

  // The following two are only valid when state_ == kAttached.
  uint64_t koid() const { return koid_; }
  const std::string& name() const { return name_; }

  // Attaches to the job with the given koid. The callback will be executed when the attach is
  // complete (or fails).
  void Attach(uint64_t koid, Callback callback);

  // Attaches to the root job. The callback will be executed when the attach is complete (or fails).
  void AttachToSystemRoot(Callback callback);

  // Attaches with the given koid and name without making IPC calls.
  void AttachForTesting(uint64_t koid, const std::string& name);

  // Detaches from the job. The callback will be executed when the detach is complete (or fails).
  void Detach(Callback callback);

  // Detaches without making any IPC calls. This can be used to clean up after AttachForTesting(),
  // and during final shutdown. In final shutdown, we assume anything still left running will
  // continue running as-is and just clean up local references.
  //
  // If the job is not running, this will do nothing.
  void ImplicitlyDetach();

  // FilterObserver implementation
  void DidCreateFilter(Filter* filter) override;
  void DidChangeFilter(Filter* filter, std::optional<Job*> previous_job) override;
  void WillDestroyFilter(Filter* filter) override;

  // Same as the two-argument version below but forces an update if the last one failed.
  // Made public because JobTest will use it.
  void SendAndUpdateFilters(std::vector<std::string> filters);

 private:
  State state_ = State::kNone;

  // Only valid when state_ is kAttached.
  uint64_t koid_ = 0;
  std::string name_;

  std::vector<std::string> filters_;
  bool is_implicit_root_ = false;
  bool last_filter_set_failed_ = false;

  fxl::WeakPtrFactory<Job> weak_factory_;

  void RefreshFilters();

  void AttachInternal(debug_ipc::TaskType type, uint64_t koid, Callback callback);

  static void OnAttachReplyThunk(fxl::WeakPtr<Job> job, Callback callback, const Err& err,
                                 uint64_t koid, const debug::Status& status,
                                 const std::string& job_name);
  void OnAttachReply(Callback callback, const Err& err, uint64_t koid, const debug::Status& status,
                     const std::string& job_name);
  void OnDetachReply(const Err& err, const debug::Status& status, Callback callback);

  // If job is running this will update |filters_| only after getting OK from agent else it will set
  // |filters_| and return.
  void SendAndUpdateFilters(std::vector<std::string> filters, bool force_send);

  FXL_DISALLOW_COPY_AND_ASSIGN(Job);
};

}  // namespace zxdb

#endif  // SRC_DEVELOPER_DEBUG_ZXDB_CLIENT_JOB_H_
