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

#include "tools/fidlcat/lib/syscall_decoder_dispatcher.h"

#include <sys/time.h>
#include <zircon/errors.h>
#include <zircon/types.h>

#include <cstdint>
#include <fstream>
#include <memory>
#include <sstream>

#include "src/developer/debug/zxdb/client/process.h"
#include "src/developer/debug/zxdb/client/thread.h"
#include "src/lib/fidl_codec/semantic.h"
#include "tools/fidlcat/lib/code_generator/test_generator.h"
#include "tools/fidlcat/lib/inference.h"
#include "tools/fidlcat/lib/interception_workflow.h"
#include "tools/fidlcat/lib/syscall_decoder.h"
#include "tools/fidlcat/lib/top.h"
#include "tools/fidlcat/proto/session.pb.h"

namespace fidlcat {

std::unique_ptr<fidl_codec::Struct> uint128_struct_definition = nullptr;

const fidl_codec::Struct& GetUint128StructDefinition() {
  if (uint128_struct_definition == nullptr) {
    uint128_struct_definition = std::make_unique<fidl_codec::Struct>("zx.uint128");
    uint128_struct_definition->AddMember("low",
                                         SyscallTypeToFidlCodecType(SyscallType::kUint64Hexa));
    uint128_struct_definition->AddMember("high",
                                         SyscallTypeToFidlCodecType(SyscallType::kUint64Hexa));
  }
  return *uint128_struct_definition;
}

std::unique_ptr<fidl_codec::Type> SyscallTypeToFidlCodecType(fidlcat::SyscallType syscall_type) {
  switch (syscall_type) {
    case SyscallType::kBool:
      return std::make_unique<fidl_codec::BoolType>();
    case SyscallType::kBtiPerm:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kBtiPerm);
    case SyscallType::kCachePolicy:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kCachePolicy);
    case SyscallType::kChannelOption:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kChannelOption);
    case SyscallType::kChar:
      return std::make_unique<fidl_codec::Int8Type>(fidl_codec::Int8Type::Kind::kChar);
    case SyscallType::kClock:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kClock);
    case SyscallType::kDuration:
      return std::make_unique<fidl_codec::Int64Type>(fidl_codec::Int64Type::Kind::kDuration);
    case SyscallType::kExceptionChannelType:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kExceptionChannelType);
    case SyscallType::kExceptionState:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kExceptionState);
    case SyscallType::kFeatureKind:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kFeatureKind);
    case SyscallType::kFutex:
      return std::make_unique<fidl_codec::Int32Type>(fidl_codec::Int32Type::Kind::kFutex);
    case SyscallType::kGpAddr:
      return std::make_unique<fidl_codec::Uint64Type>(fidl_codec::Uint64Type::Kind::kGpAddr);
    case SyscallType::kGuestTrap:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kGuestTrap);
    case SyscallType::kHandle:
      return std::make_unique<fidl_codec::HandleType>();
    case SyscallType::kInfoMapsType:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kInfoMapsType);
    case SyscallType::kInt32:
      return std::make_unique<fidl_codec::Int32Type>();
    case SyscallType::kInt64:
      return std::make_unique<fidl_codec::Int64Type>();
    case SyscallType::kInterruptFlags:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kInterruptFlags);
    case SyscallType::kIommuType:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kIommuType);
    case SyscallType::kKoid:
      return std::make_unique<fidl_codec::Uint64Type>(fidl_codec::Uint64Type::Kind::kKoid);
    case SyscallType::kKtraceControlAction:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kKtraceControlAction);
    case SyscallType::kMonotonicTime:
      return std::make_unique<fidl_codec::Int64Type>(fidl_codec::Int64Type::Kind::kMonotonicTime);
    case SyscallType::kObjectInfoTopic:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kObjectInfoTopic);
    case SyscallType::kObjType:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kObjType);
    case SyscallType::kPacketGuestVcpuType:
      return std::make_unique<fidl_codec::Uint8Type>(
          fidl_codec::Uint8Type::Kind::kPacketGuestVcpuType);
    case SyscallType::kPacketPageRequestCommand:
      return std::make_unique<fidl_codec::Uint16Type>(
          fidl_codec::Uint16Type::Kind::kPacketPageRequestCommand);
    case SyscallType::kPaddr:
      return std::make_unique<fidl_codec::Uint64Type>(fidl_codec::Uint64Type::Kind::kPaddr);
    case SyscallType::kPciBarType:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kPciBarType);
    case SyscallType::kPolicyAction:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kPolicyAction);
    case SyscallType::kPolicyCondition:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kPolicyCondition);
    case SyscallType::kPolicyTopic:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kPolicyTopic);
    case SyscallType::kPortPacketType:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kPortPacketType);
    case SyscallType::kProfileInfoFlags:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kProfileInfoFlags);
    case SyscallType::kPropType:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kPropType);
    case SyscallType::kRights:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kRights);
    case SyscallType::kRsrcKind:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kRsrcKind);
    case SyscallType::kSignals:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kSignals);
    case SyscallType::kSize:
      return std::make_unique<fidl_codec::Uint64Type>(fidl_codec::Uint64Type::Kind::kSize);
    case SyscallType::kSocketCreateOptions:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kSocketCreateOptions);
    case SyscallType::kSocketReadOptions:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kSocketReadOptions);
    case SyscallType::kSocketDisposition:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kSocketDisposition);
    case SyscallType::kStatus:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kStatus);
    case SyscallType::kSystemEventType:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kSystemEventType);
    case SyscallType::kSystemPowerctl:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kSystemPowerctl);
    case SyscallType::kThreadState:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kThreadState);
    case SyscallType::kThreadStateTopic:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kThreadStateTopic);
    case SyscallType::kTime:
      return std::make_unique<fidl_codec::Int64Type>(fidl_codec::Int64Type::Kind::kTime);
    case SyscallType::kTimerOption:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kTimerOption);
    case SyscallType::kUint8:
      return std::make_unique<fidl_codec::Uint8Type>();
    case SyscallType::kUint8Hexa:
      return std::make_unique<fidl_codec::Uint8Type>(fidl_codec::Uint8Type::Kind::kHexaDecimal);
    case SyscallType::kUint16:
      return std::make_unique<fidl_codec::Uint16Type>();
    case SyscallType::kUint16Hexa:
      return std::make_unique<fidl_codec::Uint16Type>(fidl_codec::Uint16Type::Kind::kHexaDecimal);
    case SyscallType::kUint32:
      return std::make_unique<fidl_codec::Uint32Type>();
    case SyscallType::kUint32Hexa:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kHexaDecimal);
    case SyscallType::kUint64:
      return std::make_unique<fidl_codec::Uint64Type>();
    case SyscallType::kUint64Hexa:
      return std::make_unique<fidl_codec::Uint64Type>(fidl_codec::Uint64Type::Kind::kHexaDecimal);
    case SyscallType::kUint128Hexa:
      return std::make_unique<fidl_codec::StructType>(GetUint128StructDefinition(), false);
    case SyscallType::kUintptr:
      return std::make_unique<fidl_codec::Uint64Type>(fidl_codec::Uint64Type::Kind::kUintptr);
    case SyscallType::kVaddr:
      return std::make_unique<fidl_codec::Uint64Type>(fidl_codec::Uint64Type::Kind::kVaddr);
    case SyscallType::kVcpu:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kVcpu);
    case SyscallType::kVmOption:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kVmOption);
    case SyscallType::kVmoCreationOption:
      return std::make_unique<fidl_codec::Uint32Type>(
          fidl_codec::Uint32Type::Kind::kVmoCreationOption);
    case SyscallType::kVmoOp:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kVmoOp);
    case SyscallType::kVmoOption:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kVmoOption);
    case SyscallType::kVmoType:
      return std::make_unique<fidl_codec::Uint32Type>(fidl_codec::Uint32Type::Kind::kVmoType);
    default:
      return nullptr;
  }
}

std::unique_ptr<fidl_codec::Type> AccessBase::ComputeType() const {
  return SyscallTypeToFidlCodecType(GetSyscallType());
}

std::unique_ptr<fidl_codec::Type> SyscallInputOutputBase::ComputeType() const { return nullptr; }

std::unique_ptr<fidl_codec::Value> SyscallInputOutputBase::GenerateValue(
    SyscallDecoderInterface* decoder, Stage stage) const {
  return std::make_unique<fidl_codec::InvalidValue>();
}

bool SyscallInputOutputBase::GetAutomationInstructions(
    const std::vector<debug::RegisterID>& argument_indexes, bool is_invoked,
    const std::vector<debug_ipc::AutomationCondition>& conditions, Syscall& syscall) {
  return false;
}

void SyscallFidlMessageBase::LoadBytes(SyscallDecoderInterface* decoder, Stage stage) const {
  handle_->Load(decoder, stage);
  options_->Load(decoder, stage);
  num_bytes_->Load(decoder, stage);
  if (num_bytes_->Loaded(decoder, stage)) {
    uint32_t count = num_bytes_->Value(decoder, stage);
    bool use_iovec = false;
    if ((type_ == fidl_codec::SyscallFidlType::kOutputMessage) ||
        (type_ == fidl_codec::SyscallFidlType::kOutputRequest)) {
      uint32_t options = options_->Value(decoder, stage);
      if ((options & ZX_CHANNEL_WRITE_USE_IOVEC) != 0) {
        use_iovec = true;
      }
    }
    if (count > 0) {
      if (use_iovec) {
        bytes_->LoadArray(decoder, stage, count * sizeof(zx_channel_iovec_t));
        if (bytes_->ArrayLoaded(decoder, stage, count * sizeof(zx_channel_iovec_t))) {
          auto iovec = reinterpret_cast<const zx_channel_iovec_t*>(bytes_->Content(decoder, stage));
          for (uint32_t buffer = 0; buffer < count; ++buffer) {
            decoder->LoadBuffer(stage, reinterpret_cast<uint64_t>(iovec[buffer].buffer),
                                iovec[buffer].capacity);
          }
        }
      } else {
        bytes_->LoadArray(decoder, stage, count);
      }
    }
  }
}

SyscallFidlMessageBase::ByteBuffer::ByteBuffer(SyscallDecoderInterface* decoder, Stage stage,
                                               const SyscallFidlMessageBase* from) {
  uint32_t options_value = from->options()->Value(decoder, stage);
  if (((from->type() == fidl_codec::SyscallFidlType::kOutputMessage) ||
       (from->type() == fidl_codec::SyscallFidlType::kOutputRequest)) &&
      ((options_value & ZX_CHANNEL_WRITE_USE_IOVEC) != 0)) {
    // For the iovec case, we need to concatanate all the buffers into one.
    const zx_channel_iovec_t* iovec =
        reinterpret_cast<const zx_channel_iovec_t*>(from->bytes()->Content(decoder, stage));
    uint32_t iovec_count = from->num_bytes()->Value(decoder, stage);
    for (uint32_t i = 0; i < iovec_count; ++i) {
      count_ += static_cast<uint32_t>(iovec[i].capacity);
    }
    buffer_ = new uint8_t[count_];
    uint8_t* dst = buffer_;
    for (uint32_t i = 0; i < iovec_count; ++i) {
      const uint8_t* data =
          decoder->BufferContent(stage, reinterpret_cast<uint64_t>(iovec[i].buffer));
      memcpy(dst, data, iovec[i].capacity);
      dst += iovec[i].capacity;
    }
    bytes_ = buffer_;
  } else {
    bytes_ = from->bytes()->Content(decoder, stage);
    count_ = from->num_bytes()->Value(decoder, stage);
  }
}

std::unique_ptr<fidl_codec::Type> SyscallFidlMessageHandle::ComputeType() const {
  return std::make_unique<fidl_codec::FidlMessageType>();
}

std::unique_ptr<fidl_codec::Value> SyscallFidlMessageHandle::GenerateValue(
    SyscallDecoderInterface* decoder, Stage stage) const {
  zx_handle_t handle_value = handle()->Value(decoder, stage);
  ByteBuffer buffer(decoder, stage, this);
  const zx_handle_t* handles_value = handles()->Content(decoder, stage);
  uint32_t num_handles_value = num_handles()->Value(decoder, stage);
  zx_handle_disposition_t* handle_dispositions_value = nullptr;
  if (num_handles_value > 0) {
    handle_dispositions_value = new zx_handle_disposition_t[num_handles_value];
    for (uint32_t i = 0; i < num_handles_value; ++i) {
      handle_dispositions_value[i].operation = fidl_codec::kNoHandleDisposition;
      handle_dispositions_value[i].handle = handles_value[i];
      handle_dispositions_value[i].rights = 0;
      handle_dispositions_value[i].type = ZX_OBJ_TYPE_NONE;
      handle_dispositions_value[i].result = ZX_OK;
    }
  }
  fidl_codec::DecodedMessage message;
  std::stringstream error_stream;
  message.DecodeMessage(decoder->dispatcher()->MessageDecoderDispatcher(),
                        decoder->fidlcat_thread()->process()->koid(), handle_value, buffer.bytes(),
                        buffer.count(), handle_dispositions_value, num_handles_value, type(),
                        error_stream);
  auto result = std::make_unique<fidl_codec::FidlMessageValue>(
      &message, error_stream.str(), buffer.bytes(), buffer.count(), handle_dispositions_value,
      num_handles_value);
  delete[] handle_dispositions_value;
  if (result->is_request()) {
    if (result->matched_request()) {
      decoder->set_semantic(result->method()->semantic());
      decoder->set_decoded_request(result->decoded_request());
    }
    if (result->matched_response()) {
      decoder->set_semantic(result->method()->semantic());
      decoder->set_decoded_response(result->decoded_response());
    }
  }
  return result;
}

std::unique_ptr<fidl_codec::Type> SyscallFidlMessageHandleInfo::ComputeType() const {
  return std::make_unique<fidl_codec::FidlMessageType>();
}

std::unique_ptr<fidl_codec::Value> SyscallFidlMessageHandleInfo::GenerateValue(
    SyscallDecoderInterface* decoder, Stage stage) const {
  zx_handle_t handle_value = handle()->Value(decoder, stage);
  ByteBuffer buffer(decoder, stage, this);
  const zx_handle_info_t* handle_infos_value = handles()->Content(decoder, stage);
  uint32_t num_handles_value = num_handles()->Value(decoder, stage);
  zx_handle_disposition_t* handle_dispositions_value = nullptr;
  if (num_handles_value > 0) {
    handle_dispositions_value = new zx_handle_disposition_t[num_handles_value];
    for (uint32_t i = 0; i < num_handles_value; ++i) {
      handle_dispositions_value[i].operation = fidl_codec::kNoHandleDisposition;
      handle_dispositions_value[i].handle = handle_infos_value[i].handle;
      handle_dispositions_value[i].type = handle_infos_value[i].type;
      handle_dispositions_value[i].rights = handle_infos_value[i].rights;
      handle_dispositions_value[i].result = ZX_OK;
    }
  }
  fidl_codec::DecodedMessage message;
  std::stringstream error_stream;
  message.DecodeMessage(decoder->dispatcher()->MessageDecoderDispatcher(),
                        decoder->fidlcat_thread()->process()->koid(), handle_value, buffer.bytes(),
                        buffer.count(), handle_dispositions_value, num_handles_value, type(),
                        error_stream);
  auto result = std::make_unique<fidl_codec::FidlMessageValue>(
      &message, error_stream.str(), buffer.bytes(), buffer.count(), handle_dispositions_value,
      num_handles_value);
  delete[] handle_dispositions_value;
  if (result->is_request()) {
    if (result->matched_request()) {
      decoder->set_semantic(result->method()->semantic());
      decoder->set_decoded_request(result->decoded_request());
    }
    if (result->matched_response()) {
      decoder->set_semantic(result->method()->semantic());
      decoder->set_decoded_response(result->decoded_response());
    }
  }
  return result;
}

std::unique_ptr<fidl_codec::Type> SyscallFidlMessageHandleDisposition::ComputeType() const {
  return std::make_unique<fidl_codec::FidlMessageType>();
}

std::unique_ptr<fidl_codec::Value> SyscallFidlMessageHandleDisposition::GenerateValue(
    SyscallDecoderInterface* decoder, Stage stage) const {
  zx_handle_t handle_value = handle()->Value(decoder, stage);
  ByteBuffer buffer(decoder, stage, this);
  const zx_handle_disposition_t* handle_dispositions_value = handles()->Content(decoder, stage);
  uint32_t num_handles_value = num_handles()->Value(decoder, stage);
  fidl_codec::DecodedMessage message;
  std::stringstream error_stream;
  message.DecodeMessage(decoder->dispatcher()->MessageDecoderDispatcher(),
                        decoder->fidlcat_thread()->process()->koid(), handle_value, buffer.bytes(),
                        buffer.count(), handle_dispositions_value, num_handles_value, type(),
                        error_stream);
  auto result = std::make_unique<fidl_codec::FidlMessageValue>(
      &message, error_stream.str(), buffer.bytes(), buffer.count(), handle_dispositions_value,
      num_handles_value);
  if (result->is_request()) {
    if (result->matched_request()) {
      decoder->set_semantic(result->method()->semantic());
      decoder->set_decoded_request(result->decoded_request());
    }
    if (result->matched_response()) {
      decoder->set_semantic(result->method()->semantic());
      decoder->set_decoded_response(result->decoded_response());
    }
  }
  return result;
}

void ComputeTypes(const std::vector<std::unique_ptr<SyscallInputOutputBase>>& fields,
                  std::vector<std::unique_ptr<fidl_codec::StructMember>>* inline_members,
                  std::vector<std::unique_ptr<fidl_codec::StructMember>>* outline_members) {
  for (const auto& field : fields) {
    std::unique_ptr<fidl_codec::Type> type = field->ComputeType();
    if (field->InlineValue()) {
      inline_members->emplace_back(
          std::make_unique<fidl_codec::StructMember>(field->name(), std::move(type), field->id()));
    } else {
      outline_members->emplace_back(
          std::make_unique<fidl_codec::StructMember>(field->name(), std::move(type), field->id()));
    }
  }
}

void Syscall::ComputeTypes() {
  fidlcat::ComputeTypes(inputs_, &input_inline_members_, &input_outline_members_);
  fidlcat::ComputeTypes(outputs_, &output_inline_members_, &output_outline_members_);
}

const fidl_codec::StructMember* Syscall::SearchInlineMember(const std::string& name,
                                                            bool invoked) const {
  if (invoked) {
    for (const auto& member : input_inline_members_) {
      if (member->name() == name) {
        return member.get();
      }
    }
  } else {
    for (const auto& member : output_inline_members_) {
      if (member->name() == name) {
        return member.get();
      }
    }
  }
  return nullptr;
}

const fidl_codec::StructMember* Syscall::SearchInlineMember(uint32_t id, bool invoked) const {
  if (invoked) {
    for (const auto& member : input_inline_members_) {
      if (member->id() == id) {
        return member.get();
      }
    }
  } else {
    for (const auto& member : output_inline_members_) {
      if (member->id() == id) {
        return member.get();
      }
    }
  }
  return nullptr;
}

const fidl_codec::StructMember* Syscall::SearchOutlineMember(const std::string& name,
                                                             bool invoked) const {
  if (invoked) {
    for (const auto& member : input_outline_members_) {
      if (member->name() == name) {
        return member.get();
      }
    }
  } else {
    for (const auto& member : output_outline_members_) {
      if (member->name() == name) {
        return member.get();
      }
    }
  }
  return nullptr;
}

const fidl_codec::StructMember* Syscall::SearchOutlineMember(uint32_t id, bool invoked) const {
  if (invoked) {
    for (const auto& member : input_outline_members_) {
      if (member->id() == id) {
        return member.get();
      }
    }
  } else {
    for (const auto& member : output_outline_members_) {
      if (member->id() == id) {
        return member.get();
      }
    }
  }
  return nullptr;
}

void Syscall::ComputeStatistics(const OutputEvent* event) const {
  if (compute_statistics_ != nullptr) {
    (*compute_statistics_)(event);
  }
}

bool ComputeAutomation(const std::vector<debug::RegisterID>& argument_indexes, debug::Arch arch,
                       const std::vector<std::unique_ptr<SyscallInputOutputBase>>& fields,
                       bool is_invoked, Syscall& syscall) {
  bool fully_automated = true;
  for (const auto& field : fields) {
    std::vector<debug_ipc::AutomationCondition> automation_conditions;
    for (const auto& condition : *(field->conditions())) {
      if (!condition->ComputeAutomationCondition(argument_indexes, is_invoked, arch, syscall,
                                                 automation_conditions)) {
        continue;
      }
    }
    if (!field->GetAutomationInstructions(argument_indexes, is_invoked, automation_conditions,
                                          syscall)) {
      fully_automated = false;
    }
  }
  return fully_automated;
}

void Syscall::ComputeAutomation(debug::Arch arch) {
  if (invoked_bp_instructions_.size() + exit_bp_instructions_.size() > 0) {
    return;
  }

  static const std::vector<debug::RegisterID> amd64_argument_indexes = {
      debug::RegisterID::kX64_rdi, debug::RegisterID::kX64_rsi, debug::RegisterID::kX64_rdx,
      debug::RegisterID::kX64_rcx, debug::RegisterID::kX64_r8,  debug::RegisterID::kX64_r9};

  static const std::vector<debug::RegisterID> arm64_argument_indexes = {
      debug::RegisterID::kARMv8_x0, debug::RegisterID::kARMv8_x1, debug::RegisterID::kARMv8_x2,
      debug::RegisterID::kARMv8_x3, debug::RegisterID::kARMv8_x4, debug::RegisterID::kARMv8_x5,
      debug::RegisterID::kARMv8_x6, debug::RegisterID::kARMv8_x7};
  const std::vector<debug::RegisterID>* arg_index;
  if (arch == debug::Arch::kX64) {
    arg_index = &amd64_argument_indexes;
  } else if (arch == debug::Arch::kArm64) {
    arg_index = &arm64_argument_indexes;
  } else {
    FX_LOGS(ERROR) << "Unknown architecture";
    return;
  }

  bool initial_automated = fidlcat::ComputeAutomation(*arg_index, arch, inputs_, true, *this);
  bool exit_automated = fidlcat::ComputeAutomation(*arg_index, arch, outputs_, false, *this);
  fully_automated_ = initial_automated && exit_automated;
  debug_ipc::AutomationInstruction clear_instr;
  if (invoked_bp_instructions_.size() + exit_bp_instructions_.size() > 0) {
    clear_instr.InitClearStoredValues(std::vector<debug_ipc::AutomationCondition>());
    exit_bp_instructions_.emplace_back(clear_instr);
  }
}

SyscallDecoderDispatcher::SyscallDecoderDispatcher(const DecodeOptions& decode_options)
    : decode_options_(decode_options), inference_(this) {
  Populate();
  ComputeTypes();
  if (!decode_options.trigger_filters.empty()) {
    // We have at least one trigger => wait for a message satisfying the trigger before displaying
    // any syscall.
    display_started_ = false;
  }
  if (!decode_options.message_filters.empty() || !decode_options.exclude_message_filters.empty()) {
    has_filter_ = true;
  }
  if ((decode_options.stack_level != kNoStack) || !decode_options_.save.empty()) {
    needs_stack_frame_ = true;
  }
  if (!decode_options_.save.empty()) {
    needs_to_save_events_ = true;
  } else {
    switch (decode_options_.output_mode) {
      case OutputMode::kNone:
      case OutputMode::kStandard:
        break;
      case OutputMode::kTextProtobuf:
        needs_to_save_events_ = true;
        break;
    }
  }
}

HandleInfo* SyscallDecoderDispatcher::CreateHandleInfo(Thread* thread, uint32_t handle,
                                                       int64_t creation_time, bool startup) {
  auto old_value = thread->process()->SearchHandleInfo(handle);
  if (old_value != nullptr) {
    return old_value;
  }
  auto result = std::make_unique<HandleInfo>(thread, handle, creation_time, startup);
  auto returned_value = result.get();
  thread->process()->handle_infos().emplace_back(result.get());
  thread->process()->handle_info_map().emplace(std::make_pair(handle, result.get()));
  handle_infos_.emplace_back(std::move(result));
  return returned_value;
}

void SyscallDecoderDispatcher::DecodeSyscall(InterceptingThreadObserver* thread_observer,
                                             zxdb::Thread* thread, Syscall* syscall,
                                             uint64_t timestamp) {
  uint64_t thread_id = thread->GetKoid();
  auto current = syscall_decoders_.find(thread_id);
  if (current != syscall_decoders_.end()) {
    FX_LOGS(ERROR) << thread->GetProcess()->GetName() << ' ' << thread->GetProcess()->GetKoid()
                   << ':' << thread_id << ": Internal error: already decoding the thread";
    return;
  }
  auto decoder =
      std::make_unique<SyscallDecoder>(this, thread_observer, thread, syscall, timestamp);
  auto tmp = decoder.get();
  syscall_decoders_[thread_id] = std::move(decoder);
  tmp->Decode();
}

void SyscallDecoderDispatcher::DecodeException(InterceptionWorkflow* workflow, zxdb::Thread* thread,
                                               uint64_t timestamp) {
  uint64_t thread_id = thread->GetKoid();
  auto current = exception_decoders_.find(thread_id);
  if (current != exception_decoders_.end()) {
    FX_LOGS(ERROR) << thread->GetProcess()->GetName() << ' ' << thread->GetProcess()->GetKoid()
                   << ':' << thread_id
                   << ": Internal error: already decoding an exception for the thread";
    return;
  }
  auto decoder = std::make_unique<ExceptionDecoder>(workflow, this, thread, timestamp);
  auto tmp = decoder.get();
  exception_decoders_[thread_id] = std::move(decoder);
  tmp->Decode();
}

void SyscallDecoderDispatcher::DeleteDecoder(SyscallDecoder* decoder) {
  if (!decoder->aborted()) {
    zxdb::Thread* thread = decoder->get_thread();
    if (thread != nullptr) {
      thread->Continue(false);
    }
  }
  syscall_decoders_.erase(decoder->fidlcat_thread()->koid());
}

void SyscallDecoderDispatcher::DeleteDecoder(ExceptionDecoder* decoder) {
  zxdb::Thread* thread = decoder->get_thread();
  if (thread != nullptr) {
    thread->Continue(false);
  }
  exception_decoders_.erase(decoder->thread_id());
}

void SyscallDecoderDispatcher::AddStopMonitoringEvent(std::shared_ptr<StopMonitoringEvent> event) {
  for (const auto& decoder : syscall_decoders_) {
    if (decoder.second->fidlcat_thread()->process() == event->process()) {
      decoder.second->set_aborted();
    }
  }
}

void SyscallDecoderDispatcher::SaveEvent(std::shared_ptr<Event> event) {
  if (needs_to_save_events()) {
    decoded_events_.emplace_back(std::move(event));
  }
}

void SyscallDecoderDispatcher::SessionEnded() {
  bool generate_proto_session = false;
  if (!decode_options_.save.empty()) {
    generate_proto_session = true;
  } else {
    switch (decode_options_.output_mode) {
      case OutputMode::kNone:
      case OutputMode::kStandard:
        break;
      case OutputMode::kTextProtobuf:
        generate_proto_session = true;
        break;
    }
  }
  if (generate_proto_session) {
    proto::Session session;
    GenerateProtoSession(&session);
    if (!decode_options_.save.empty()) {
      std::fstream output(decode_options_.save, std::ios::out | std::ios::trunc | std::ios::binary);
      if (output.fail()) {
        FX_LOGS(ERROR) << "Can't open <" << decode_options_.save << "> for writing.";
      } else if (!session.SerializeToOstream(&output)) {
        FX_LOGS(ERROR) << "Failed to write session to protobuf file <" << decode_options_.save
                       << ">.";
      }
    }
    switch (decode_options_.output_mode) {
      case OutputMode::kNone:
      case OutputMode::kStandard:
        break;
      case OutputMode::kTextProtobuf:
        std::cout << session.DebugString();
        break;
    }
  }
}

void SyscallDecoderDispatcher::GenerateProtoSession(proto::Session* session) {
  for (const auto& process : processes_) {
    proto::Process* proto_process = session->add_process();
    proto_process->set_koid(process.second->koid());
    proto_process->set_name(process.second->name());
    auto process_semantic = inference().GetProcessSemantic(process.second->koid());
    if (process_semantic != nullptr) {
      for (const auto& linked_handles : process_semantic->linked_handles) {
        if (linked_handles.first < linked_handles.second) {
          proto::LinkedHandles* proto_linked_handles = proto_process->add_linked_handles();
          proto_linked_handles->set_handle_0(linked_handles.first);
          proto_linked_handles->set_handle_1(linked_handles.second);
        }
      }
    }
  }
  for (const auto& thread : threads_) {
    proto::Thread* proto_thread = session->add_thread();
    proto_thread->set_koid(thread.second->koid());
    proto_thread->set_process_koid(thread.second->process()->koid());
  }
  for (const auto& handle_info : handle_infos_) {
    fidl_codec::semantic::InferredHandleInfo* inferred_handle_info =
        inference().GetInferredHandleInfo(handle_info->thread()->process()->koid(),
                                          handle_info->handle());
    proto::HandleDescription* proto_handle_description = session->add_handle_description();
    proto_handle_description->set_handle(handle_info->handle());
    proto_handle_description->set_thread_koid(handle_info->thread()->koid());
    proto_handle_description->set_creation_time(handle_info->creation_time());
    proto_handle_description->set_startup(handle_info->startup());
    if (inferred_handle_info != nullptr) {
      proto_handle_description->set_type(inferred_handle_info->type());
      proto_handle_description->set_fd(inferred_handle_info->fd());
      proto_handle_description->set_path(inferred_handle_info->path());
      proto_handle_description->set_attributes(inferred_handle_info->attributes());
    }
    proto_handle_description->set_koid(handle_info->koid());
    proto_handle_description->set_object_type(handle_info->object_type());
  }
  for (const auto& linked_koids : inference().linked_koids()) {
    if (linked_koids.first < linked_koids.second) {
      proto::LinkedKoids* proto_linked_koids = session->add_linked_koids();
      proto_linked_koids->set_koid_0(linked_koids.first);
      proto_linked_koids->set_koid_1(linked_koids.second);
    }
  }
  for (const auto& event : decoded_events_) {
    event->Write(session->add_event());
  }
}

void SyscallDecoderDispatcher::ComputeTypes() {
  for (const auto& syscall : syscalls_) {
    syscall.second->ComputeTypes();
  }
}

double SyscallDisplayDispatcher::GetTime(int64_t timestamp) {
  return static_cast<double>(timestamp) / 1000000000;
}

void SyscallDisplayDispatcher::AddProcessLaunchedEvent(
    std::shared_ptr<ProcessLaunchedEvent> event) {
  if (decode_options().output_mode == OutputMode::kStandard) {
    if (!decode_options().thread_filters.empty()) {
      return;
    }
    os_ << '\n' << colors().green << GetTime(event->timestamp()) << colors().reset << ' ';
    if (event->error_message().empty()) {
      os_ << colors().green << "Launched " << colors().blue << event->command() << colors().reset
          << '\n';
    } else {
      os_ << colors().red << "Can't launch " << colors().blue << event->command() << colors().reset
          << " : " << colors().red << event->error_message() << colors().reset << '\n';
    }
  }

  SaveEvent(std::move(event));
}

void SyscallDisplayDispatcher::AddProcessMonitoredEvent(
    std::shared_ptr<ProcessMonitoredEvent> event) {
  if (!decode_options().thread_filters.empty()) {
    return;
  }
  if (decode_options().output_mode == OutputMode::kStandard) {
    os_ << '\n' << colors().green << GetTime(event->timestamp()) << colors().reset << ' ';
    if (event->error_message().empty()) {
      os_ << colors().green << "Monitoring ";
    } else {
      os_ << colors().red << "Can't monitor ";
    }

    if (event->process()->name().empty()) {
      os_ << colors().reset << "process with koid ";
    } else {
      os_ << colors().blue << event->process()->name() << colors().reset << " koid=";
    }

    os_ << colors().red << event->process()->koid() << colors().reset;
    if (!event->error_message().empty()) {
      os_ << " : " << colors().red << event->error_message() << colors().reset;
    }
    os_ << '\n';
  }

  SaveEvent(std::move(event));
}

void SyscallDisplayDispatcher::AddStopMonitoringEvent(std::shared_ptr<StopMonitoringEvent> event) {
  if (!decode_options().thread_filters.empty()) {
    return;
  }
  if (decode_options().output_mode == OutputMode::kStandard) {
    os_ << '\n' << colors().green << GetTime(event->timestamp()) << colors().reset << ' ';
    if (event->process()->name().empty()) {
      os_ << colors().green << "Stop monitoring process with koid" << colors().reset;
    } else {
      os_ << colors().green << "Stop monitoring" << colors().reset << ' ' << colors().blue
          << event->process()->name() << colors().reset << " koid";
    }
    os_ << ' ' << colors().red << event->process()->koid() << colors().reset << '\n';
  }

  SaveEvent(event);

  SyscallDecoderDispatcher::AddStopMonitoringEvent(std::move(event));
}

void SyscallDisplayDispatcher::SyscallDecodingError(const fidlcat::Thread* fidlcat_thread,
                                                    const Syscall* syscall,
                                                    const DecoderError& error) {
  std::string message = error.message();
  size_t pos = 0;
  for (;;) {
    size_t end = message.find('\n', pos);
    os_ << fidlcat_thread->process()->name() << ' ' << colors().red
        << fidlcat_thread->process()->koid() << colors().reset << ':' << colors().red
        << fidlcat_thread->koid() << colors().reset << ' ' << syscall->name() << ": "
        << colors().red << error.message().substr(pos, end) << colors().reset << '\n';
    if (end == std::string::npos) {
      break;
    }
    pos = end + 1;
  }
  os_ << '\n';
}

void SyscallDisplayDispatcher::AddInvokedEvent(std::shared_ptr<InvokedEvent> invoked_event) {
  invoked_event->set_id(GetNextInvokedEventId());
  if (!extra_generation().empty()) {
    invoked_event->ComputeHandleInfo(this);
  }
  if (!invoked_event->thread()->displayed()) {
    return;
  }
  if (!display_started()) {
    // The user specified a trigger. Check if this is a message which satisfies one of the triggers.
    const fidl_codec::FidlMessageValue* message = invoked_event->GetMessage();
    if ((message == nullptr) || (message->method() == nullptr) ||
        !decode_options().IsTrigger(message->method()->fully_qualified_name())) {
      return;
    }
    // We found a trigger => allow the display.
    set_display_started();
  }
  if (has_filter() && invoked_event->syscall()->has_fidl_message()) {
    // We have filters and this is a syscalls with a FIDL message.
    // Only display the syscall if the message satifies the conditions.
    const fidl_codec::FidlMessageValue* message = invoked_event->GetMessage();
    if ((message == nullptr) || (message->method() == nullptr) ||
        !decode_options().SatisfiesMessageFilters(message->method()->fully_qualified_name())) {
      return;
    }
  }
  invoked_event->set_displayed();
  DisplayInvokedEvent(invoked_event.get());

  SaveEvent(std::move(invoked_event));
}

void SyscallDisplayDispatcher::AddOutputEvent(std::shared_ptr<OutputEvent> output_event) {
  if (!output_event->thread()->displayed()) {
    return;
  }
  if (!extra_generation().empty()) {
    if (output_event->invoked_event()->handle_info() != nullptr) {
      output_event->invoked_event()->handle_info()->AddEvent(output_event.get());
    }
    output_event->syscall()->ComputeStatistics(output_event.get());
  }
  if (!output_event->invoked_event()->displayed()) {
    // The display of the syscall wasn't allowed by the input arguments. Check if the output
    // arguments allows its display.
    if (!display_started()) {
      // The user specified a trigger. Check if this is a message which satisfies one of the
      // triggers.
      const fidl_codec::FidlMessageValue* message = output_event->GetMessage();
      if ((message == nullptr) || (message->method() == nullptr) ||
          !decode_options().IsTrigger(message->method()->fully_qualified_name())) {
        return;
      }
      set_display_started();
    }
    if (has_filter() && output_event->syscall()->has_fidl_message()) {
      // We have filters and this is a syscalls with a FIDL message.
      // Only display the syscall if the message satifies the conditions.
      const fidl_codec::FidlMessageValue* message = output_event->GetMessage();
      if ((message == nullptr) || (message->method() == nullptr) ||
          !decode_options().SatisfiesMessageFilters(message->method()->fully_qualified_name())) {
        return;
      }
    }
    // We can display the syscall but the inputs have not been displayed => display the inputs
    // before displaying the outputs.
    DisplayInvokedEvent(output_event->invoked_event());
  }

  DisplayOutputEvent(output_event.get());

  SaveEvent(std::move(output_event));
}

void SyscallDisplayDispatcher::AddExceptionEvent(std::shared_ptr<ExceptionEvent> exception_event) {
  if (!exception_event->thread()->displayed()) {
    return;
  }

  DisplayExceptionEvent(exception_event.get());

  SaveEvent(std::move(exception_event));
}

void SyscallDisplayDispatcher::SessionEnded() {
  SyscallDecoderDispatcher::SessionEnded();
  if (!decoded_events().empty()) {
    // Uses the first event for the timestamp reference.
    GetTime(decoded_events().front()->timestamp());
  }
  const char* separator = "";
  for (const auto& extra_generation : extra_generation()) {
    if (extra_generation.path.empty()) {
      os_ << separator;
      switch (extra_generation.kind) {
        case ExtraGeneration::Kind::kSummary:
          DisplaySummary(os_);
          break;
        case ExtraGeneration::Kind::kTop: {
          Top top(this);
          top.Display(os_);
          break;
        }
        case ExtraGeneration::Kind::kThreads:
          DisplayThreads(os_);
          break;
        case ExtraGeneration::Kind::kCpp:
          GenerateTests("/tmp/fidlcat-generated-tests/" + std::to_string(std::time(0)));
          break;
      }
      separator = "\n";
    } else {
      if (extra_generation.kind == ExtraGeneration::Kind::kCpp) {
        GenerateTests(extra_generation.path);
      } else {
        std::fstream output(extra_generation.path, std::ios::out | std::ios::trunc);
        if (output.fail()) {
          FX_LOGS(ERROR) << "Can't open <" << extra_generation.path << "> for writing.";
        } else {
          switch (extra_generation.kind) {
            case ExtraGeneration::Kind::kSummary:
              DisplaySummary(output);
              break;
            case ExtraGeneration::Kind::kTop: {
              Top top(this);
              top.Display(output);
              break;
            }
            case ExtraGeneration::Kind::kThreads:
              DisplayThreads(output);
              break;
            case ExtraGeneration::Kind::kCpp:
              break;
          }
        }
      }
    }
  }
}

void SyscallDisplayDispatcher::DisplayInvokedEvent(const InvokedEvent* invoked_event) {
  if (decode_options().output_mode != OutputMode::kStandard) {
    return;
  }
  std::string line_header =
      colors().green + std::to_string(GetTime(invoked_event->timestamp())) + colors().reset + ' ' +
      invoked_event->thread()->process()->name() + ' ' + colors().red +
      std::to_string(invoked_event->thread()->process()->koid()) + colors().reset + ':' +
      colors().red + std::to_string(invoked_event->thread()->koid()) + colors().reset + ' ';
  if (with_process_info()) {
    os_ << line_header;
  }
  os_ << '\n';

  FidlcatPrinter printer(this, invoked_event->thread()->process(), os_, line_header);

  // We have been able to create values from the syscall => print them.
  invoked_event->PrettyPrint(printer);
  last_displayed_event_ = invoked_event;
}

void SyscallDisplayDispatcher::DisplayOutputEvent(const OutputEvent* output_event) {
  if (decode_options().output_mode != OutputMode::kStandard) {
    return;
  }
  if (output_event->syscall()->return_type() != SyscallReturnType::kNoReturn) {
    if (last_displayed_event_ != output_event->invoked_event()) {
      // Add a blank line to tell the user that this display is not linked to the
      // previous displayed lines.
      os_ << "\n";
    }
    std::string line_header;
    if (with_process_info() || (last_displayed_event_ != output_event->invoked_event())) {
      line_header = colors().green + std::to_string(GetTime(output_event->timestamp())) +
                    colors().reset + ' ' + output_event->thread()->process()->name() + ' ' +
                    colors().red + std::to_string(output_event->thread()->process()->koid()) +
                    colors().reset + ':' + colors().red +
                    std::to_string(output_event->thread()->koid()) + colors().reset + ' ';
    } else {
      line_header = colors().green + std::to_string(GetTime(output_event->timestamp())) +
                    colors().reset + ' ';
    }
    FidlcatPrinter printer(this, output_event->thread()->process(), os_, line_header);
    // We have been able to create values from the syscall => print them.
    output_event->PrettyPrint(printer);

    last_displayed_event_ = output_event;
  }
}

void SyscallDisplayDispatcher::DisplayExceptionEvent(const ExceptionEvent* exception_event) {
  if (decode_options().output_mode != OutputMode::kStandard) {
    return;
  }
  os_ << '\n';

  std::string line_header =
      colors().green + std::to_string(GetTime(exception_event->timestamp())) + colors().reset +
      ' ' + exception_event->thread()->process()->name() + ' ' + colors().red +
      std::to_string(exception_event->thread()->process()->koid()) + colors().reset + ':' +
      colors().red + std::to_string(exception_event->thread()->koid()) + colors().reset + ' ';
  FidlcatPrinter printer(this, exception_event->thread()->process(), os_, line_header);
  exception_event->PrettyPrint(printer);
}

void SyscallCompareDispatcher::SyscallDecodingError(const fidlcat::Thread* fidlcat_thread,
                                                    const Syscall* syscall,
                                                    const DecoderError& error) {
  os_.clear();
  os_.str("");
  SyscallDisplayDispatcher::SyscallDecodingError(fidlcat_thread, syscall, error);
  comparator_->DecodingError(os_.str());
}

void SyscallCompareDispatcher::DisplayInvokedEvent(const InvokedEvent* invoked_event) {
  os_.clear();
  os_.str("");
  SyscallDisplayDispatcher::DisplayInvokedEvent(invoked_event);
  comparator_->CompareInput(os_.str(), invoked_event->thread()->process()->name(),
                            invoked_event->thread()->process()->koid(),
                            invoked_event->thread()->koid());
}

void SyscallCompareDispatcher::DisplayOutputEvent(const OutputEvent* output_event) {
  os_.clear();
  os_.str("");
  SyscallDisplayDispatcher::DisplayOutputEvent(output_event);
  if (output_event->syscall()->return_type() != SyscallReturnType::kNoReturn) {
    comparator_->CompareOutput(os_.str(), output_event->thread()->process()->name(),
                               output_event->thread()->process()->koid(),
                               output_event->thread()->koid());
  }
}

void SyscallDisplayDispatcher::GenerateTests(const std::string& output_directory) {
  auto test_generator = TestGenerator(this, output_directory);
  test_generator.GenerateTests();
}

}  // namespace fidlcat
