// Copyright 2020 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 TOOLS_FIDLCAT_LIB_EVENT_H_
#define TOOLS_FIDLCAT_LIB_EVENT_H_

#include <zircon/types.h>

#include <map>
#include <memory>
#include <vector>

#include "src/developer/debug/zxdb/client/process.h"
#include "src/lib/fidl_codec/wire_object.h"
#include "src/lib/fidl_codec/wire_types.h"
#include "src/lib/fxl/memory/weak_ptr.h"
#include "tools/fidlcat/lib/fidlcat_printer.h"
#include "tools/fidlcat/proto/session.pb.h"

namespace fidlcat {

class Event;
class Location;
class OutputEvent;
class Syscall;
class SyscallDecoder;
class SyscallDisplayDispatcher;
class Thread;

class HandleSession {
 public:
  HandleSession() = default;

  const OutputEvent* creation_event() const { return creation_event_; }
  void set_creation_event(const OutputEvent* creation_event) { creation_event_ = creation_event; }

  const std::vector<const Event*>& events() const { return events_; }
  void add_event(const Event* event) { events_.emplace_back(event); }

  const OutputEvent* close_event() const { return close_event_; }
  void set_close_event(const OutputEvent* close_event) { close_event_ = close_event; }

 private:
  // The event which created the session.
  const OutputEvent* creation_event_ = nullptr;
  // All the regular events which use the handle during the session.
  std::vector<const Event*> events_;
  // The event which closed the session.
  const OutputEvent* close_event_ = nullptr;
};

class HandleInfo {
 public:
  HandleInfo(Thread* thread, uint32_t handle, int64_t creation_time, bool startup)
      : thread_(thread), handle_(handle), creation_time_(creation_time), startup_(startup) {}

  Thread* thread() const { return thread_; }
  uint32_t handle() const { return handle_; }
  int64_t creation_time() const { return creation_time_; }
  bool startup() const { return startup_; }
  void set_startup() { startup_ = true; }
  zx_obj_type_t object_type() const { return object_type_; }
  void set_object_type(zx_obj_type_t object_type) { object_type_ = object_type; }
  zx_rights_t rights() const { return rights_; }
  void set_rights(zx_rights_t rights) { rights_ = rights; }
  zx_koid_t koid() const { return koid_; }
  void set_koid(zx_koid_t koid) { koid_ = koid; }
  const std::vector<std::unique_ptr<HandleSession>>& sessions() const { return sessions_; }

  void AddCreationEvent(const OutputEvent* creation_event) {
    auto session = std::make_unique<HandleSession>();
    session->set_creation_event(creation_event);
    sessions_.emplace_back(std::move(session));
  }

  void AddEvent(const Event* event) {
    if (!sessions_.empty()) {
      HandleSession* session = sessions_.back().get();
      if (session->close_event() == nullptr) {
        session->add_event(event);
        return;
      }
    }
    auto session = std::make_unique<HandleSession>();
    session->add_event(event);
    sessions_.emplace_back(std::move(session));
  }

  void AddCloseEvent(const OutputEvent* close_event) {
    if (!sessions_.empty()) {
      HandleSession* session = sessions_.back().get();
      if (session->close_event() == nullptr) {
        session->set_close_event(close_event);
        return;
      }
    }
    auto session = std::make_unique<HandleSession>();
    session->set_close_event(close_event);
    sessions_.emplace_back(std::move(session));
  }

 private:
  Thread* const thread_;
  const uint32_t handle_;
  const int64_t creation_time_;
  bool startup_;
  // The object type for the handle.
  zx_obj_type_t object_type_ = ZX_OBJ_TYPE_NONE;
  // The rights for the handle.
  zx_rights_t rights_ = 0;
  // The unique id assigned by the kernel to the object referenced by the handle.
  zx_koid_t koid_ = ZX_KOID_INVALID;
  // All the sessions for the handle. Usually, it will contain at most one session. However, some
  // processes send a handle to themself (some tests, for example, use this feature). In that case,
  // we will have several sessions for one handle.
  std::vector<std::unique_ptr<HandleSession>> sessions_;
};

// A FIDL method used by one process.
class Method {
 public:
  explicit Method(const fidl_codec::ProtocolMethod* method) : method_(method) {}

  const fidl_codec::ProtocolMethod* method() const { return method_; }
  size_t event_count() const { return events_.size(); }
  const std::vector<const OutputEvent*>& events() const { return events_; }

  void AddEvent(const OutputEvent* event) { events_.emplace_back(event); }

 private:
  // The FIDL method.
  const fidl_codec::ProtocolMethod* const method_;
  // All the vents for this method (for one process).
  std::vector<const OutputEvent*> events_;
};

// A FIDL protocol (interface) used by one process.
class Protocol {
 public:
  explicit Protocol(const fidl_codec::Protocol* interface) : interface_(interface) {}

  const fidl_codec::Protocol* interface() const { return interface_; }
  const std::map<fidl_codec::Ordinal64, std::unique_ptr<Method>>& methods() const {
    return methods_;
  }
  uint64_t event_count() const { return event_count_; }

  Method* GetMethod(fidl_codec::Ordinal64 ordinal, const fidl_codec::ProtocolMethod* method) {
    auto result = methods_.find(ordinal);
    if (result != methods_.end()) {
      return result->second.get();
    }
    auto new_method = std::make_unique<Method>(method);
    auto returned_value = new_method.get();
    methods_.emplace(std::make_pair(ordinal, std::move(new_method)));
    return returned_value;
  }

  void AddEvent(const OutputEvent* event, const fidl_codec::FidlMessageValue* message);

 private:
  // The FIDL interface.
  const fidl_codec::Protocol* const interface_;
  // All the methods of this interface used by one process.
  std::map<fidl_codec::Ordinal64, std::unique_ptr<Method>> methods_;
  // The event count for this interface for one process.
  uint64_t event_count_ = 0;
};

class Process {
 public:
  Process(std::string_view name, zx_koid_t koid, fxl::WeakPtr<zxdb::Process> zxdb_process)
      : name_(name), koid_(koid), zxdb_process_(zxdb_process) {}

  const std::string& name() const { return name_; }
  zx_koid_t koid() const { return koid_; }
  zxdb::Process* zxdb_process() const { return zxdb_process_.get(); }
  std::vector<HandleInfo*>& handle_infos() { return handle_infos_; }
  std::map<uint32_t, HandleInfo*>& handle_info_map() { return handle_info_map_; }
  const std::map<const fidl_codec::Protocol*, std::unique_ptr<Protocol>>& protocols() const {
    return protocols_;
  }
  uint64_t event_count() const { return event_count_; }

  void LoadHandleInfo(Inference* inference);

  HandleInfo* SearchHandleInfo(uint32_t handle) const {
    auto result = handle_info_map_.find(handle);
    if (result == handle_info_map_.end()) {
      return nullptr;
    }
    return result->second;
  }

  Protocol* GetProtocol(const fidl_codec::Protocol* interface) {
    auto result = protocols_.find(interface);
    if (result != protocols_.end()) {
      return result->second.get();
    }
    auto protocol = std::make_unique<Protocol>(interface);
    auto returned_value = protocol.get();
    protocols_.emplace(std::make_pair(interface, std::move(protocol)));
    return returned_value;
  }

  void AddEvent(const OutputEvent* event, const fidl_codec::FidlMessageValue* message);

 private:
  // The name of the process.
  const std::string name_;
  // The koid of the process.
  const zx_koid_t koid_;
  // The zxdb process for the koid.
  fxl::WeakPtr<zxdb::Process> zxdb_process_;
  // True if we are currently loading information about the process' handles.
  bool loading_handle_info_ = false;
  // True if we need to load again the info after the current load will be finished.
  bool needs_to_load_handle_info_ = false;
  // All the handles used by the process (first used handle first).
  std::vector<HandleInfo*> handle_infos_;
  // A map to quickly find a handle for a process.
  std::map<uint32_t, HandleInfo*> handle_info_map_;
  // All the protocols used by the process.
  std::map<const fidl_codec::Protocol*, std::unique_ptr<Protocol>> protocols_;
  // The count of events (read/write/call) for this process.
  uint64_t event_count_ = 0;
};

inline FidlcatPrinter& operator<<(FidlcatPrinter& printer, const Process& process) {
  printer << process.name() << ' ' << fidl_codec::Red << process.koid() << fidl_codec::ResetColor;
  return printer;
}

class Thread {
 public:
  Thread(Process* process, zx_koid_t koid, bool displayed)
      : process_(process), koid_(koid), displayed_(displayed) {}

  Process* process() const { return process_; }
  zx_koid_t koid() const { return koid_; }
  bool displayed() const { return displayed_; }

 private:
  Process* const process_;
  const zx_koid_t koid_;
  const bool displayed_;
};

// Defines a location in the source (used by stack frames).
class Location {
 public:
  Location(const std::string& path, uint32_t line, uint32_t column, uint64_t address,
           const std::string& symbol)
      : path_(path), line_(line), column_(column), address_(address), symbol_(symbol) {}

  const std::string& path() const { return path_; }
  uint32_t line() const { return line_; }
  uint32_t column() const { return column_; }
  uint64_t address() const { return address_; }
  const std::string& symbol() const { return symbol_; }

 private:
  const std::string path_;
  const uint32_t line_;
  const uint32_t column_;
  const uint64_t address_;
  const std::string symbol_;
};

class Event {
 public:
  explicit Event(int64_t timestamp) : timestamp_(timestamp) {}
  virtual ~Event() = default;

  // Timestamp in nanoseconds.
  int64_t timestamp() const { return timestamp_; }

  // Returns true if the event is associated to the thread.
  virtual bool ForThread(Thread* thread) const { return false; }

  // Method to downcast an event
  virtual OutputEvent* AsOutputEvent() { return nullptr; }

  // Write the content of the event into a protobuf event.
  virtual void Write(proto::Event* dst) const = 0;

  // Display a short version of the event (without all the details).
  virtual void Display(FidlcatPrinter& printer, bool with_channel = false) const {}

 private:
  const int64_t timestamp_;
};

// Event which gives the result of a process launching.
class ProcessLaunchedEvent final : public Event {
 public:
  ProcessLaunchedEvent(int64_t timestamp, std::string_view command, std::string_view error_message)
      : Event(timestamp), command_(command), error_message_(error_message) {}

  const std::string& command() const { return command_; }
  const std::string& error_message() const { return error_message_; }

  void Write(proto::Event* dst) const override;

 private:
  const std::string command_;
  const std::string error_message_;
};

// Event which tells that we started monitoring a process.
class ProcessMonitoredEvent final : public Event {
 public:
  ProcessMonitoredEvent(int64_t timestamp, Process* process, std::string_view error_message)
      : Event(timestamp), process_(process), error_message_(error_message) {}

  Process* process() const { return process_; }
  const std::string& error_message() const { return error_message_; }

  void Write(proto::Event* dst) const override;

 private:
  Process* const process_;
  const std::string error_message_;
};

// Event which tells that we stop monitoring a process.
class StopMonitoringEvent final : public Event {
 public:
  StopMonitoringEvent(int64_t timestamp, Process* process) : Event(timestamp), process_(process) {}

  Process* process() const { return process_; }

  void Write(proto::Event* dst) const override;

 private:
  Process* const process_;
};

// Base classe for all events related to a thread.
class ThreadEvent : public Event {
 public:
  ThreadEvent(int64_t timestamp, Thread* thread) : Event(timestamp), thread_(thread) {}

  Thread* thread() const { return thread_; }

  bool ForThread(Thread* thread) const override { return thread == thread_; }

 private:
  Thread* const thread_;
};

// Base class for events related to a syscall.
class SyscallEvent : public ThreadEvent {
 public:
  SyscallEvent(int64_t timestamp, Thread* thread, const Syscall* syscall)
      : ThreadEvent(timestamp, thread), syscall_(syscall) {}

  const Syscall* syscall() const { return syscall_; }

  const std::map<const fidl_codec::StructMember*, std::unique_ptr<fidl_codec::Value>>&
  inline_fields() const {
    return inline_fields_;
  }
  const std::map<const fidl_codec::StructMember*, std::unique_ptr<fidl_codec::Value>>&
  outline_fields() const {
    return outline_fields_;
  }

  void AddInlineField(const fidl_codec::StructMember* member,
                      std::unique_ptr<fidl_codec::Value> value) {
    inline_fields_.emplace(std::make_pair(member, std::move(value)));
  }

  void AddOutlineField(const fidl_codec::StructMember* member,
                       std::unique_ptr<fidl_codec::Value> value) {
    outline_fields_.emplace(std::make_pair(member, std::move(value)));
  }

  // Returns true if we need to load information about the handle (call to zx_object_get_info with
  // ZX_INFO_HANDLE_TABLE). We need to load information about the handle if one of the handles of
  // the event has an unknown koid.
  bool NeedsToLoadHandleInfo(Inference* inference);

  const fidl_codec::FidlMessageValue* GetMessage() const;

  const fidl_codec::Value* GetValue(const fidl_codec::StructMember* member) const;

  const fidl_codec::HandleValue* GetHandleValue(const fidl_codec::StructMember* member) const;

  HandleInfo* GetHandleInfo(const fidl_codec::StructMember* member) const;

 private:
  const Syscall* const syscall_;
  std::map<const fidl_codec::StructMember*, std::unique_ptr<fidl_codec::Value>> inline_fields_;
  std::map<const fidl_codec::StructMember*, std::unique_ptr<fidl_codec::Value>> outline_fields_;
};

// Event that represents the arguments of a syscall (When the syscall is called).
class InvokedEvent final : public SyscallEvent {
 public:
  InvokedEvent(int64_t timestamp, Thread* thread, const Syscall* syscall)
      : SyscallEvent(timestamp, thread, syscall) {}

  uint32_t id() const { return id_; }
  void set_id(uint32_t id) { id_ = id; }

  const std::vector<Location>& stack_frame() const { return stack_frame_; }
  std::vector<Location>& stack_frame() { return stack_frame_; }

  bool displayed() const { return displayed_; }
  void set_displayed() { displayed_ = true; }

  HandleInfo* handle_info() const { return handle_info_; }

  // For syscalls which read/write a FIDL message, computes the handle used to read/write the
  // message.
  void ComputeHandleInfo(SyscallDisplayDispatcher* dispatcher);

  void Write(proto::Event* dst) const override;

  void PrettyPrint(FidlcatPrinter& printer) const;

 public:
  uint32_t id_ = 0;
  std::vector<Location> stack_frame_;
  bool displayed_ = false;
  // For syscalls which read/write a FIDL message, the handle used to read/write the message.
  HandleInfo* handle_info_ = nullptr;
};

// The result of a function that returns >64 bits.
using result128_t = struct {
  int64_t first_word;
  uint64_t second_word;
};

// Represents the return of a value from the syscall.  Typically, this is an
// integer status code, but zx_system_get_version_string returns a zx_string_view_t, so
// we provide something generic.
class ReturnEvent final : public SyscallEvent {
 public:
  ReturnEvent(int64_t timestamp, Thread* thread, const Syscall* syscall,
              int64_t scalar_return_value)
      : SyscallEvent(timestamp, thread, syscall),
        scalar_return_value_({.first_word = scalar_return_value, .second_word = 0}) {}

  ReturnEvent(int64_t timestamp, Thread* thread, const Syscall* syscall,
              result128_t scalar_return_value)
      : SyscallEvent(timestamp, thread, syscall), scalar_return_value_(scalar_return_value) {}

  void SetReturnValue(std::unique_ptr<fidl_codec::Value> value) {
    return_value_ = std::move(value);
  }

  void Write(proto::Event* dst) const override;

  const fidl_codec::Value* GetValue() const { return return_value_.get(); }

  void SetValue(SyscallDecoder* decoder);

  // Returns a fidl_codec::Type corresponding to the return type of the syscall.
  std::unique_ptr<fidl_codec::Type> Type();

  // Returns the first 64 bits of the raw return value, which is typically the
  // result status of the function.
  uint64_t return_code() const { return scalar_return_value_.first_word; }

 private:
  const result128_t scalar_return_value_;
  std::unique_ptr<fidl_codec::Value> return_value_;
};

// Event that represents the return value and out parameters when a syscall returns.
class OutputEvent final : public SyscallEvent {
 public:
  OutputEvent(int64_t timestamp, Thread* thread, const Syscall* syscall,
              std::shared_ptr<ReturnEvent> return_event,
              std::shared_ptr<InvokedEvent> invoked_event)
      : SyscallEvent(timestamp, thread, syscall),
        returned_value_(return_event),
        invoked_event_(std::move(invoked_event)) {}

  const fidl_codec::Value* returned_value() const { return returned_value_->GetValue(); }
  const InvokedEvent* invoked_event() const { return invoked_event_.get(); }

  OutputEvent* AsOutputEvent() override { return this; }

  void Write(proto::Event* dst) const override;

  void Display(FidlcatPrinter& printer, bool with_channel) const override;

  void PrettyPrint(FidlcatPrinter& printer) const;

 private:
  // const int64_t returned_value_;
  std::shared_ptr<ReturnEvent> returned_value_;

  // The event which describes the input arguments for this syscall output event.
  std::shared_ptr<InvokedEvent> invoked_event_;
};

// Event that represents an exception.
class ExceptionEvent final : public ThreadEvent {
 public:
  ExceptionEvent(int64_t timestamp, Thread* thread) : ThreadEvent(timestamp, thread) {}

  const std::vector<Location>& stack_frame() const { return stack_frame_; }
  std::vector<Location>& stack_frame() { return stack_frame_; }

  void Write(proto::Event* dst) const override;

  void PrettyPrint(FidlcatPrinter& printer) const;

 private:
  std::vector<Location> stack_frame_;
};

// Class to decode events from protobuf.
class EventDecoder {
 public:
  explicit EventDecoder(SyscallDisplayDispatcher* dispatcher) : dispatcher_(dispatcher) {}

  SyscallDisplayDispatcher* dispatcher() const { return dispatcher_; }

  // Decodes a protobuf event and dispatch it.
  bool DecodeAndDispatchEvent(const proto::Event& proto_event);

 private:
  // Decode the values for a syscall event.
  bool DecodeValues(
      SyscallEvent* event,
      const ::google::protobuf::Map<::std::string, ::fidl_codec::proto::Value>& inline_fields,
      const ::google::protobuf::Map<uint32_t, ::fidl_codec::proto::Value>& inline_id_fields,
      const ::google::protobuf::Map<::std::string, ::fidl_codec::proto::Value>& outline_fields,
      const ::google::protobuf::Map<uint32_t, ::fidl_codec::proto::Value>& outline_id_fields,
      bool invoked);

  // Dispatcher used to decode the events.
  SyscallDisplayDispatcher* dispatcher_;

  // Map of all invoked events already decoded. Used to associate the invoked event to an output
  // event.
  std::map<uint32_t, std::shared_ptr<InvokedEvent>> invoked_events_;
};

}  // namespace fidlcat

#endif  // TOOLS_FIDLCAT_LIB_EVENT_H_
