// Copyright 2022 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 "src/developer/process_explorer/process_data.h"

#include <unordered_map>

#include "third_party/rapidjson/include/rapidjson/document.h"
#include "third_party/rapidjson/include/rapidjson/rapidjson.h"
#include "third_party/rapidjson/include/rapidjson/stringbuffer.h"
#include "third_party/rapidjson/include/rapidjson/writer.h"

namespace process_explorer {

std::string WriteProcessesDataAsJson(std::vector<Process> processes_data) {
  rapidjson::Document json_document;
  json_document.SetObject();
  auto& allocator = json_document.GetAllocator();

  rapidjson::Value processes_json(rapidjson::kArrayType);
  processes_json.Reserve((unsigned int)processes_data.size(), allocator);

  for (const auto& process : processes_data) {
    rapidjson::Value process_objects_json(rapidjson::kArrayType);
    process_objects_json.Reserve((unsigned int)process.objects.size(), allocator);

    for (const auto& object : process.objects) {
      rapidjson::Value object_json(rapidjson::kObjectType);
      object_json.AddMember("object_type", object.object_type, allocator)
          .AddMember("koid", object.koid, allocator)
          .AddMember("related_koid", object.related_koid, allocator)
          .AddMember("peer_owner_koid", object.peer_owner_koid, allocator);
      process_objects_json.PushBack(object_json, allocator);
    }

    rapidjson::Value process_name(rapidjson::kObjectType);
    const std::string s(process.name);
    process_name.SetString(s.c_str(), static_cast<rapidjson::SizeType>(s.length()), allocator);

    rapidjson::Value process_json(rapidjson::kObjectType);
    process_json.AddMember("koid", process.koid, allocator)
        .AddMember("name", process_name, allocator)
        .AddMember("objects", process_objects_json, allocator);
    processes_json.PushBack(process_json, allocator);
  }

  json_document.AddMember("Processes", processes_json, allocator);

  rapidjson::StringBuffer buffer;
  buffer.Clear();
  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
  json_document.Accept(writer);

  return std::string(buffer.GetString(), buffer.GetSize());
}

zx_status_t GetHandles(zx::unowned_process process, std::vector<zx_info_handle_extended_t>* out) {
  size_t avail = 8;

  while (true) {
    out->resize(avail);
    auto size = avail * sizeof(zx_info_handle_extended_t);
    size_t actual = 0;
    if (auto status = process->get_info(ZX_INFO_HANDLE_TABLE, out->data(), size, &actual, &avail);
        status != ZX_OK) {
      return status;
    }
    if (actual < avail) {
      avail *= 2u;
      continue;
    }
    out->resize(actual);
    return ZX_OK;
  }
}

void FillPeerOwnerKoid(std::vector<Process>& processes_data) {
  std::unordered_map<zx_koid_t, zx_koid_t> object_to_process;
  for (const Process& process : processes_data) {
    for (const KernelObject& object : process.objects) {
      if (object.related_koid != 0) {
        object_to_process[object.related_koid] = process.koid;
      }
    }
  }

  for (Process& process : processes_data) {
    for (KernelObject& object : process.objects) {
      if (object.related_koid != 0) {
        if (object_to_process.find(object.koid) == object_to_process.end())
          continue;
        object.peer_owner_koid = object_to_process[object.koid];
      }
    }
  }
}

}  // namespace process_explorer
