//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Interpreter/ScriptedInstanceRegistry.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Utility/AnsiTerminal.h"
#include "lldb/Utility/Stream.h"

#include "llvm/ADT/StringMap.h"

using namespace lldb;
using namespace lldb_private;

static bool HasArgs(const ScriptedInstanceInfo &info) {
  return info.args_sp && info.args_sp->GetSize();
}

static bool CreatedBefore(const ScriptedInstanceInfo &lhs,
                          const ScriptedInstanceInfo &rhs) {
  return lhs.id < rhs.id;
}

uint64_t ScriptedInstanceRegistry::Add(ScriptedInstanceInfo info) {
  std::lock_guard<std::mutex> guard(m_mutex);
  const uint64_t id = m_next_id++;
  info.id = id;
  info.uuid = UUID::Generate();
  m_instances[id] = std::move(info);
  return id;
}

void ScriptedInstanceRegistry::Remove(uint64_t id) {
  std::lock_guard<std::mutex> guard(m_mutex);
  m_instances.erase(id);
}

std::vector<ScriptedInstanceInfo>
ScriptedInstanceRegistry::CopyInstances() const {
  std::lock_guard<std::mutex> guard(m_mutex);
  std::vector<ScriptedInstanceInfo> instances;
  instances.reserve(m_instances.size());
  for (const auto &entry : m_instances)
    instances.push_back(entry.second);
  return instances;
}

std::vector<ScriptedInstanceInfo>
ScriptedInstanceRegistry::GetInstances() const {
  std::vector<ScriptedInstanceInfo> instances = CopyInstances();
  llvm::sort(instances, CreatedBefore);
  return instances;
}

bool ScriptedInstanceGroup::operator<(
    const ScriptedInstanceGroup &other) const {
  if (class_name != other.class_name)
    return class_name < other.class_name;

  const std::string path = source_path.GetPath();
  const std::string other_path = other.source_path.GetPath();
  if (path != other_path)
    return path < other_path;

  return extension < other.extension;
}

std::vector<ScriptedInstanceGroup> ScriptedInstanceRegistry::GetInstanceGroups(
    llvm::ArrayRef<ScriptedExtension> extensions) const {
  // Unknown names map to eScriptedExtensionInvalid, the zero value.
  llvm::StringMap<ScriptedExtension> extension_by_plugin;
  for (size_t i = 0; i < PluginManager::GetNumScriptedInterfaces(); i++)
    extension_by_plugin[PluginManager::GetScriptedInterfaceNameAtIndex(i)] =
        PluginManager::GetScriptedInterfaceExtensionAtIndex(i);

  std::vector<ScriptedInstanceGroup> groups;
  for (ScriptedInstanceInfo &info : CopyInstances()) {
    ScriptedExtension extension = extension_by_plugin.lookup(info.plugin_name);
    if (!extensions.empty() && !llvm::is_contained(extensions, extension))
      continue;

    auto it = llvm::find_if(groups, [&](const ScriptedInstanceGroup &group) {
      return group.class_name == info.class_name &&
             group.source_path == info.source_path &&
             group.extension == extension;
    });
    if (it == groups.end()) {
      it = groups.insert(groups.end(), ScriptedInstanceGroup());
      it->class_name = info.class_name;
      it->extension = extension;
      it->source_path = info.source_path;
    }
    it->instances.push_back(std::move(info));
  }

  for (ScriptedInstanceGroup &group : groups)
    llvm::sort(group.instances, CreatedBefore);
  llvm::sort(groups);
  return groups;
}

StructuredData::DictionarySP ScriptedInstanceGroup::ToStructuredData() const {
  auto group_sp = std::make_shared<StructuredData::Dictionary>();
  group_sp->AddStringItem("class_name", class_name);
  group_sp->AddStringItem("extension",
                          ScriptInterpreter::ExtensionToString(extension));
  if (source_path)
    group_sp->AddStringItem("source_path", source_path.GetPath());

  auto instances_sp = std::make_shared<StructuredData::Array>();
  for (const ScriptedInstanceInfo &info : instances) {
    auto instance_sp = std::make_shared<StructuredData::Dictionary>();
    instance_sp->AddStringItem("uuid", info.uuid.GetAsString());
    if (info.object_address != LLDB_INVALID_ADDRESS)
      instance_sp->AddIntegerItem("address", info.object_address);
    if (HasArgs(info))
      instance_sp->AddItem("args", info.args_sp);
    instances_sp->AddItem(instance_sp);
  }
  group_sp->AddItem("instances", instances_sp);
  return group_sp;
}

void ScriptedInstanceGroup::Dump(Stream &s, const Debugger &debugger,
                                 bool use_color) const {
  auto ansi_code = [use_color](llvm::StringRef code) {
    return ansi::FormatAnsiTerminalCodes(code, use_color);
  };
  const std::string label_prefix = ansi_code(debugger.GetLabelAnsiPrefix());
  const std::string label_suffix = ansi_code(debugger.GetLabelAnsiSuffix());
  const std::string title_prefix = ansi_code(debugger.GetTitleAnsiPrefix());
  const std::string title_suffix = ansi_code(debugger.GetTitleAnsiSuffix());

  auto print_label = [&](llvm::StringRef indent, llvm::StringRef label) {
    s << indent << label_prefix << label << ':' << label_suffix;
  };
  auto print_instance = [&](const ScriptedInstanceInfo &info) {
    s << info.uuid.GetAsString();
    if (info.object_address != LLDB_INVALID_ADDRESS)
      s.Format(" ({0:x})", info.object_address);
    s << '\n';
  };
  auto print_args = [&](const ScriptedInstanceInfo &info,
                        llvm::StringRef indent) {
    if (!HasArgs(info))
      return;
    print_label(indent, "Args");
    s << '\n';
    info.args_sp->ForEachSorted(
        [&](llvm::StringRef key, StructuredData::Object *value) {
          s << indent << "  - " << key << ": ";
          if (StructuredData::String *str = value->GetAsString())
            s << str->GetValue();
          else
            value->Dump(s, /*pretty_print=*/false);
          s << '\n';
          return true;
        });
  };

  print_label("  ", "Class");
  s << ' ' << title_prefix << class_name << title_suffix << '\n';
  print_label("  ", "Extension");
  s << ' ' << ScriptInterpreter::ExtensionToString(extension) << '\n';
  if (source_path) {
    print_label("  ", "Path");
    s << ' ' << source_path.GetPath() << '\n';
  }

  if (instances.size() == 1) {
    print_label("  ", "Instance");
    s << ' ';
    print_instance(instances.front());
    print_args(instances.front(), "  ");
    return;
  }

  print_label("  ", "Instances");
  s << '\n';
  for (auto [idx, info] : llvm::enumerate(instances)) {
    s.Format("    [{0}] ", idx);
    print_instance(info);
    print_args(info, "        ");
  }
}
