// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#ifndef RUNTIME_VM_SERVICE_EVENT_H_
#define RUNTIME_VM_SERVICE_EVENT_H_

#include "vm/globals.h"
#include "vm/heap/heap.h"

namespace dart {

class ActivationFrame;
class Breakpoint;
class Instance;
class Isolate;
class IsolateGroup;
class Object;
class StreamInfo;
class String;
class TimelineEventBlock;

class ServiceEvent {
 public:
  enum EventKind {
    kVMUpdate,      // VM identity information has changed
    kVMFlagUpdate,  // VM flags updated

    kIsolateStart,           // New isolate has started
    kIsolateRunnable,        // Isolate is ready to run
    kIsolateExit,            // Isolate has exited
    kIsolateUpdate,          // Isolate identity information has changed
    kIsolateReload,          // Result of a reload request
    kServiceExtensionAdded,  // A service extension was registered

    kPauseStart,  // --pause-isolates-on-start
    kPauseExit,   // --pause-isolates-on-exit
    kPauseBreakpoint,
    kPauseInterrupted,
    kPauseException,
    kPausePostRequest,  // isolate is paused after a service request.
    kNone,              // isolate has not been made runnable yet.
    kResume,
    kBreakpointAdded,
    kBreakpointResolved,
    kBreakpointRemoved,
    kBreakpointUpdated,
    kInspect,
    kDebuggerSettingsUpdate,

    kGC,

    kEmbedder,

    kLogging,

    kExtension,

    kTimelineEvents,
    // Sent when SetVMTimelineFlags is called.
    kTimelineStreamSubscriptionsUpdate,

    kUserTagChanged,

    kIllegal,
  };

  struct LogRecord {
    int64_t sequence_number;
    int64_t timestamp;
    intptr_t level;
    const String* name;
    const String* message;
    const Instance* zone;
    const Object* error;
    const Instance* stack_trace;
  };

  struct ExtensionEvent {
    const String* event_kind;
    const String* event_data;
  };

  explicit ServiceEvent(EventKind event_kind);
  ServiceEvent(IsolateGroup* isolate_group, EventKind event_kind);
  ServiceEvent(Isolate* isolate, EventKind event_kind);

  Isolate* isolate() const { return isolate_; }
  IsolateGroup* isolate_group() const { return isolate_group_; }

  // Used by the C embedding api.
  Dart_Port isolate_id() const { return isolate_->main_port(); }

  EventKind kind() const { return kind_; }

  bool IsPause() const {
    switch (kind()) {
      case kPauseStart:
      case kPauseExit:
      case kPauseBreakpoint:
      case kPauseInterrupted:
      case kPauseException:
      case kPausePostRequest:
        return true;
      default:
        return false;
    }
  }

  const char* flag_name() const { return flag_name_; }
  void set_flag_name(const char* flag) { flag_name_ = flag; }

  const char* flag_new_value() const { return flag_new_value_; }
  void set_flag_new_value(const char* value) { flag_new_value_ = value; }

  const char* previous_tag() const { return previous_tag_; }
  void set_previous_tag(const char* previous_tag) {
    previous_tag_ = previous_tag;
  }

  const char* updated_tag() const { return updated_tag_; }
  void set_updated_tag(const char* updated_tag) { updated_tag_ = updated_tag; }

  const char* embedder_kind() const { return embedder_kind_; }

  const char* KindAsCString() const;

  void set_embedder_kind(const char* embedder_kind) {
    embedder_kind_ = embedder_kind;
  }

  const StreamInfo* stream_info() const;
  const char* stream_id() const;

  void set_embedder_stream_id(const char* stream_id) {
    embedder_stream_id_ = stream_id;
  }

  Breakpoint* breakpoint() const { return breakpoint_; }
  void set_breakpoint(Breakpoint* bpt) {
    ASSERT(kind() == kPauseBreakpoint || kind() == kBreakpointAdded ||
           kind() == kBreakpointResolved || kind() == kBreakpointRemoved ||
           kind() == kBreakpointUpdated);
    breakpoint_ = bpt;
  }

  ActivationFrame* top_frame() const { return top_frame_; }
  void set_top_frame(ActivationFrame* frame) {
    ASSERT(kind() == kPauseBreakpoint || kind() == kPauseInterrupted ||
           kind() == kPauseException || kind() == kPausePostRequest ||
           kind() == kResume);
    top_frame_ = frame;
  }

  const String* extension_rpc() const { return extension_rpc_; }
  void set_extension_rpc(const String* extension_rpc) {
    extension_rpc_ = extension_rpc;
  }

  const Object* exception() const { return exception_; }
  void set_exception(const Object* exception) {
    ASSERT(kind_ == kPauseException);
    exception_ = exception;
  }

  const Error* reload_error() const {
    ASSERT(kind_ == kIsolateReload);
    return reload_error_;
  }
  void set_reload_error(const Error* error) {
    ASSERT(kind_ == kIsolateReload);
    reload_error_ = error;
  }

  bool at_async_jump() const { return at_async_jump_; }
  void set_at_async_jump(bool value) { at_async_jump_ = value; }

  const Object* inspectee() const { return inspectee_; }
  void set_inspectee(const Object* inspectee) {
    ASSERT(kind_ == kInspect);
    inspectee_ = inspectee;
  }

  const Heap::GCStats* gc_stats() const { return gc_stats_; }

  void set_gc_stats(const Heap::GCStats* gc_stats) { gc_stats_ = gc_stats; }

  const uint8_t* bytes() const { return bytes_; }

  intptr_t bytes_length() const { return bytes_length_; }

  void set_bytes(const uint8_t* bytes, intptr_t bytes_length) {
    bytes_ = bytes;
    bytes_length_ = bytes_length;
  }

  void set_log_record(const LogRecord& log_record) { log_record_ = log_record; }

  void set_extension_event(const ExtensionEvent& extension_event) {
    extension_event_ = extension_event;
  }

  void UpdateTimestamp();

  int64_t timestamp() const { return timestamp_; }

  const TimelineEventBlock* timeline_event_block() const {
    return timeline_event_block_;
  }

  void set_timeline_event_block(const TimelineEventBlock* block) {
    ASSERT(kind() == kTimelineEvents);
    timeline_event_block_ = block;
  }

  void PrintJSON(JSONStream* js) const;

  void PrintJSONHeader(JSONObject* jsobj) const;

 private:
  ServiceEvent(IsolateGroup* isolate_group,
               Isolate* isolate,
               EventKind event_kind);

  Isolate* isolate_;
  IsolateGroup* isolate_group_;
  EventKind kind_;
  const char* flag_name_;
  const char* flag_new_value_;
  const char* previous_tag_;
  const char* updated_tag_;
  const char* embedder_kind_;
  const char* embedder_stream_id_;
  Breakpoint* breakpoint_;
  ActivationFrame* top_frame_;
  const TimelineEventBlock* timeline_event_block_;
  const String* extension_rpc_;
  const Object* exception_;
  const Error* reload_error_;
  const String* spawn_token_;
  const String* spawn_error_;
  bool at_async_jump_;
  const Object* inspectee_;
  const Heap::GCStats* gc_stats_;
  const uint8_t* bytes_;
  intptr_t bytes_length_;
  LogRecord log_record_;
  ExtensionEvent extension_event_;
  int64_t timestamp_;
};

}  // namespace dart

#endif  // RUNTIME_VM_SERVICE_EVENT_H_
