// Copyright 2020 the V8 project 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/v8windbg/src/v8-debug-helper-interop.h"

#include <Windows.h>
#include <crtdbg.h>

#include "src/common/globals.h"
#include "tools/debug_helper/debug-helper.h"
#include "tools/v8windbg/base/utilities.h"
#include "tools/v8windbg/src/v8windbg-extension.h"

namespace d = v8::debug_helper;

// We need a plain C function pointer for interop with v8_debug_helper. We can
// use this to get one as long as we never need two at once.
class MemReaderScope {
 public:
  explicit MemReaderScope(WRL::ComPtr<IDebugHostContext> sp_context)
      : sp_context_(sp_context) {
    _ASSERTE(!context_);
    context_ = sp_context_.Get();
  }
  ~MemReaderScope() { context_ = nullptr; }
  d::MemoryAccessor GetReader() { return &MemReaderScope::Read; }

 private:
  MemReaderScope(const MemReaderScope&) = delete;
  MemReaderScope& operator=(const MemReaderScope&) = delete;
  static d::MemoryAccessResult Read(uintptr_t address, void* destination,
                                    size_t byte_count) {
    ULONG64 bytes_read;
    Location loc{address};
    HRESULT hr = sp_debug_host_memory->ReadBytes(context_, loc, destination,
                                                 byte_count, &bytes_read);
    // TODO determine when an address is valid but inaccessible
    return SUCCEEDED(hr) ? d::MemoryAccessResult::kOk
                         : d::MemoryAccessResult::kAddressNotValid;
  }
  WRL::ComPtr<IDebugHostContext> sp_context_;
  static IDebugHostContext* context_;
};
IDebugHostContext* MemReaderScope::context_;

StructField::StructField(std::u16string field_name, std::u16string type_name,
                         std::string uncompressed_type_name, uint64_t offset,
                         uint8_t num_bits, uint8_t shift_bits)
    : name(field_name),
      type_name(type_name),
      uncompressed_type_name(uncompressed_type_name),
      offset(offset),
      num_bits(num_bits),
      shift_bits(shift_bits) {}
StructField::~StructField() = default;
StructField::StructField(const StructField&) = default;
StructField::StructField(StructField&&) = default;
StructField& StructField::operator=(const StructField&) = default;
StructField& StructField::operator=(StructField&&) = default;

Property::Property(std::u16string property_name, std::u16string type_name,
                   std::string uncompressed_type_name, uint64_t address,
                   size_t item_size)
    : name(property_name),
      type(PropertyType::kPointer),
      type_name(type_name),
      uncompressed_type_name(uncompressed_type_name),
      addr_value(address),
      item_size(item_size) {}
Property::~Property() = default;
Property::Property(const Property&) = default;
Property::Property(Property&&) = default;
Property& Property::operator=(const Property&) = default;
Property& Property::operator=(Property&&) = default;

V8HeapObject::V8HeapObject() = default;
V8HeapObject::~V8HeapObject() = default;
V8HeapObject::V8HeapObject(const V8HeapObject&) = default;
V8HeapObject::V8HeapObject(V8HeapObject&&) = default;
V8HeapObject& V8HeapObject::operator=(const V8HeapObject&) = default;
V8HeapObject& V8HeapObject::operator=(V8HeapObject&&) = default;

std::vector<Property> GetPropertiesAsVector(size_t num_properties,
                                            d::ObjectProperty** properties) {
  std::vector<Property> result;
  for (size_t property_index = 0; property_index < num_properties;
       ++property_index) {
    const auto& source_prop = *(properties)[property_index];
    Property dest_prop(ConvertToU16String(source_prop.name),
                       ConvertToU16String(source_prop.type),
                       source_prop.decompressed_type, source_prop.address,
                       source_prop.size);
    if (source_prop.kind != d::PropertyKind::kSingle) {
      dest_prop.type = PropertyType::kArray;
      dest_prop.length = source_prop.num_values;
    }
    if (dest_prop.type_name.empty() || source_prop.num_struct_fields > 0) {
      // If the helper library didn't provide a type, then it should have
      // provided struct fields instead. Set the struct type flag and copy the
      // fields into the result.
      dest_prop.type =
          static_cast<PropertyType>(static_cast<int>(dest_prop.type) |
                                    static_cast<int>(PropertyType::kStruct));
      for (size_t field_index = 0; field_index < source_prop.num_struct_fields;
           ++field_index) {
        const auto& struct_field = *source_prop.struct_fields[field_index];
        dest_prop.fields.push_back({ConvertToU16String(struct_field.name),
                                    ConvertToU16String(struct_field.type),
                                    struct_field.decompressed_type,
                                    struct_field.offset, struct_field.num_bits,
                                    struct_field.shift_bits});
      }
    }
    result.push_back(dest_prop);
  }
  return result;
}

V8HeapObject GetHeapObject(WRL::ComPtr<IDebugHostContext> sp_context,
                           uint64_t tagged_ptr, uint64_t referring_pointer,
                           const char* type_name, bool is_compressed) {
  // Read the value at the address, and see if it is a tagged pointer

  V8HeapObject obj;
  MemReaderScope reader_scope(sp_context);

  d::HeapAddresses heap_addresses = {0, 0, 0, 0};
  // TODO ideally we'd provide real heap page pointers. For now, just testing
  // decompression based on the pointer to wherever we found this value,
  // which is likely (though not guaranteed) to be a heap pointer itself.
  heap_addresses.any_heap_pointer = referring_pointer;

  auto props = d::GetObjectProperties(tagged_ptr, reader_scope.GetReader(),
                                      heap_addresses, type_name);
  obj.friendly_name = ConvertToU16String(props->brief);
  obj.properties =
      GetPropertiesAsVector(props->num_properties, props->properties);

  // For each guessed type, create a synthetic property that will request data
  // about the same object again but with a more specific type hint.
  if (referring_pointer != 0) {
    for (size_t type_index = 0; type_index < props->num_guessed_types;
         ++type_index) {
      const std::string& type_name = props->guessed_types[type_index];
      Property dest_prop(
          ConvertToU16String(("guessed type " + type_name).c_str()),
          ConvertToU16String(is_compressed ? kTaggedValue : type_name),
          type_name, referring_pointer,
          is_compressed ? i::kTaggedSize : sizeof(void*));
      obj.properties.push_back(dest_prop);
    }
  }

  return obj;
}

std::vector<std::u16string> ListObjectClasses() {
  const d::ClassList* class_list = d::ListObjectClasses();
  std::vector<std::u16string> result;
  for (size_t i = 0; i < class_list->num_class_names; ++i) {
    result.push_back(ConvertToU16String(class_list->class_names[i]));
  }
  return result;
}

const char* BitsetName(uint64_t payload) { return d::BitsetName(payload); }

std::vector<Property> GetStackFrame(WRL::ComPtr<IDebugHostContext> sp_context,

                                    uint64_t frame_pointer) {
  MemReaderScope reader_scope(sp_context);
  auto props = d::GetStackFrame(static_cast<uintptr_t>(frame_pointer),
                                reader_scope.GetReader());
  return GetPropertiesAsVector(props->num_properties, props->properties);
}
