//===----------------------------------------------------------------------===//
//
// 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/Target/SyntheticFrameProvider.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Interpreter/Interfaces/ScriptedFrameProviderInterface.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"

using namespace lldb;
using namespace lldb_private;

SyntheticFrameProvider::SyntheticFrameProvider(StackFrameListSP input_frames)
    : m_input_frames(std::move(input_frames)) {}

SyntheticFrameProvider::~SyntheticFrameProvider() = default;

void ScriptedFrameProviderDescriptor::Dump(Stream *s) const {
  if (!s)
    return;

  s->Format("  ID: {0:x}\n", GetID());
  s->Printf("  Name: %s\n", GetName().str().c_str());

  std::string description = GetDescription();
  if (!description.empty())
    s->Printf("  Description: %s\n", description.c_str());

  // Show priority information.
  std::optional<uint32_t> priority = GetPriority();
  if (priority.has_value())
    s->Printf("  Priority: %u\n", *priority);
  else
    s->PutCString("  Priority: Default (no priority specified)\n");

  // Show thread filter information.
  if (thread_specs.empty()) {
    s->PutCString("  Thread Filter: (applies to all threads)\n");
  } else {
    s->Printf("  Thread Filter: %zu specification(s)\n", thread_specs.size());
    for (size_t i = 0; i < thread_specs.size(); ++i) {
      const ThreadSpec &spec = thread_specs[i];
      s->Printf("    [%zu] ", i);
      spec.GetDescription(s, lldb::eDescriptionLevelVerbose);
      s->PutChar('\n');
    }
  }
}

uint32_t ScriptedFrameProviderDescriptor::GetID() const {
  if (!scripted_metadata_sp)
    return 0;

  return scripted_metadata_sp->GetID();
}

std::string ScriptedFrameProviderDescriptor::GetDescription() const {
  // If we have an interface, call get_description() to fetch it.
  if (interface_sp && scripted_metadata_sp)
    return interface_sp->GetDescription(scripted_metadata_sp->GetClassName());
  return {};
}

std::optional<uint32_t> ScriptedFrameProviderDescriptor::GetPriority() const {
  // If we have an interface, call get_priority() to fetch it.
  if (interface_sp && scripted_metadata_sp)
    return interface_sp->GetPriority(scripted_metadata_sp->GetClassName());
  return std::nullopt;
}

llvm::Expected<SyntheticFrameProviderSP> SyntheticFrameProvider::CreateInstance(
    StackFrameListSP input_frames,
    const ScriptedFrameProviderDescriptor &descriptor) {
  if (!input_frames)
    return llvm::createStringError(
        "cannot create synthetic frame provider: invalid input frames");

  // Iterate through all registered ScriptedFrameProvider plugins.
  for (auto create_callback :
       PluginManager::GetScriptedFrameProviderCreateCallbacks()) {
    auto provider_or_err = create_callback(input_frames, descriptor);
    if (!provider_or_err) {
      LLDB_LOG_ERROR(GetLog(LLDBLog::Target), provider_or_err.takeError(),
                     "Failed to create synthetic frame provider: {0}");
      continue;
    }

    if (auto frame_provider_up = std::move(*provider_or_err))
      return std::move(frame_provider_up);
  }

  return llvm::createStringError(
      "cannot create synthetic frame provider: no suitable plugin found");
}

llvm::Expected<SyntheticFrameProviderSP> SyntheticFrameProvider::CreateInstance(
    StackFrameListSP input_frames, llvm::StringRef plugin_name,
    const std::vector<ThreadSpec> &thread_specs) {
  if (!input_frames)
    return llvm::createStringError(
        "cannot create synthetic frame provider: invalid input frames");

  // Look up the specific C++ plugin by name.
  SyntheticFrameProviderCreateInstance create_callback =
      PluginManager::GetSyntheticFrameProviderCreateCallbackForPluginName(
          plugin_name);

  if (!create_callback)
    return llvm::createStringError(
        "cannot create synthetic frame provider: C++ plugin '%s' not found",
        plugin_name.str().c_str());

  auto provider_or_err = create_callback(input_frames, thread_specs);
  if (!provider_or_err)
    return provider_or_err.takeError();

  if (auto frame_provider_sp = std::move(*provider_or_err))
    return std::move(frame_provider_sp);

  return llvm::createStringError(
      "cannot create synthetic frame provider: C++ plugin '%s' returned null",
      plugin_name.str().c_str());
}
