//===-- ScriptedPythonInterface.cpp ---------------------------------------===//
//
// 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-python.h"

#include "lldb/Host/Config.h"
#include "lldb/Utility/Log.h"
#include "lldb/lldb-enumerations.h"

#include "../ScriptInterpreterPythonImpl.h"
#include "ScriptedPythonInterface.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/ValueObject/ValueObjectList.h"
#include <optional>

using namespace lldb;
using namespace lldb_private;

ScriptedPythonInterface::ScriptedPythonInterface(
    ScriptInterpreterPythonImpl &interpreter)
    : ScriptedInterface(), m_interpreter(interpreter) {}

template <>
StructuredData::ArraySP
ScriptedPythonInterface::ExtractValueFromPythonObject<StructuredData::ArraySP>(
    python::PythonObject &p, Status &error) {
  python::PythonList result_list(python::PyRefType::Borrowed, p.get());
  return result_list.CreateStructuredArray();
}

template <>
StructuredData::DictionarySP
ScriptedPythonInterface::ExtractValueFromPythonObject<
    StructuredData::DictionarySP>(python::PythonObject &p, Status &error) {
  python::PythonDictionary result_dict(python::PyRefType::Borrowed, p.get());
  return result_dict.CreateStructuredDictionary();
}

template <>
Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>(
    python::PythonObject &p, Status &error) {
  if (lldb::SBError *sb_error = reinterpret_cast<lldb::SBError *>(
          python::LLDBSWIGPython_CastPyObjectToSBError(p.get())))
    return m_interpreter.GetStatusFromSBError(*sb_error);
  error =
      Status::FromErrorString("Couldn't cast lldb::SBError to lldb::Status.");

  return {};
}

template <>
Event *ScriptedPythonInterface::ExtractValueFromPythonObject<Event *>(
    python::PythonObject &p, Status &error) {
  if (lldb::SBEvent *sb_event = reinterpret_cast<lldb::SBEvent *>(
          python::LLDBSWIGPython_CastPyObjectToSBEvent(p.get())))
    return m_interpreter.GetOpaqueTypeFromSBEvent(*sb_event);
  error = Status::FromErrorString(
      "Couldn't cast lldb::SBEvent to lldb_private::Event.");

  return nullptr;
}

template <>
lldb::StreamSP
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StreamSP>(
    python::PythonObject &p, Status &error) {
  if (lldb::SBStream *sb_stream = reinterpret_cast<lldb::SBStream *>(
          python::LLDBSWIGPython_CastPyObjectToSBStream(p.get())))
    return m_interpreter.GetOpaqueTypeFromSBStream(*sb_stream);
  error = Status::FromErrorString(
      "Couldn't cast lldb::SBStream to lldb_private::Stream.");

  return nullptr;
}

template <>
lldb::StackFrameSP
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StackFrameSP>(
    python::PythonObject &p, Status &error) {
  if (lldb::SBFrame *sb_frame = reinterpret_cast<lldb::SBFrame *>(
          python::LLDBSWIGPython_CastPyObjectToSBFrame(p.get())))
    return m_interpreter.GetOpaqueTypeFromSBFrame(*sb_frame);
  error = Status::FromErrorString(
      "Couldn't cast lldb::SBFrame to lldb_private::StackFrame.");

  return nullptr;
}

template <>
lldb::ThreadSP
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::ThreadSP>(
    python::PythonObject &p, Status &error) {
  if (lldb::SBThread *sb_thread = reinterpret_cast<lldb::SBThread *>(
          python::LLDBSWIGPython_CastPyObjectToSBThread(p.get())))
    return m_interpreter.GetOpaqueTypeFromSBThread(*sb_thread);
  error = Status::FromErrorString(
      "Couldn't cast lldb::SBThread to lldb_private::Thread.");

  return nullptr;
}

template <>
SymbolContext
ScriptedPythonInterface::ExtractValueFromPythonObject<SymbolContext>(
    python::PythonObject &p, Status &error) {
  if (lldb::SBSymbolContext *sb_symbol_context =
          reinterpret_cast<lldb::SBSymbolContext *>(
              python::LLDBSWIGPython_CastPyObjectToSBSymbolContext(p.get())))
    return m_interpreter.GetOpaqueTypeFromSBSymbolContext(*sb_symbol_context);
  error = Status::FromErrorString(
      "Couldn't cast lldb::SBSymbolContext to lldb_private::SymbolContext.");

  return {};
}

template <>
lldb::DataExtractorSP
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>(
    python::PythonObject &p, Status &error) {
  lldb::SBData *sb_data = reinterpret_cast<lldb::SBData *>(
      python::LLDBSWIGPython_CastPyObjectToSBData(p.get()));

  if (!sb_data) {
    error = Status::FromErrorStringWithFormat(
        "Couldn't cast lldb::SBData to lldb::DataExtractorSP.");
    return nullptr;
  }

  return m_interpreter.GetDataExtractorFromSBData(*sb_data);
}

template <>
lldb::BreakpointSP
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::BreakpointSP>(
    python::PythonObject &p, Status &error) {
  lldb::SBBreakpoint *sb_breakpoint = reinterpret_cast<lldb::SBBreakpoint *>(
      python::LLDBSWIGPython_CastPyObjectToSBBreakpoint(p.get()));

  if (!sb_breakpoint) {
    error = Status::FromErrorStringWithFormat(
        "Couldn't cast lldb::SBBreakpoint to lldb::BreakpointSP.");
    return nullptr;
  }

  return m_interpreter.GetOpaqueTypeFromSBBreakpoint(*sb_breakpoint);
}

template <>
lldb::BreakpointLocationSP
ScriptedPythonInterface::ExtractValueFromPythonObject<
    lldb::BreakpointLocationSP>(python::PythonObject &p, Status &error) {
  lldb::SBBreakpointLocation *sb_break_loc =
      reinterpret_cast<lldb::SBBreakpointLocation *>(
          python::LLDBSWIGPython_CastPyObjectToSBBreakpointLocation(p.get()));

  if (!sb_break_loc) {
    error = Status::FromErrorStringWithFormat(
        "Couldn't cast lldb::SBBreakpointLocation to "
        "lldb::BreakpointLocationSP.");
    return nullptr;
  }

  return m_interpreter.GetOpaqueTypeFromSBBreakpointLocation(*sb_break_loc);
}

template <>
lldb::ProcessAttachInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject<
    lldb::ProcessAttachInfoSP>(python::PythonObject &p, Status &error) {
  lldb::SBAttachInfo *sb_attach_info = reinterpret_cast<lldb::SBAttachInfo *>(
      python::LLDBSWIGPython_CastPyObjectToSBAttachInfo(p.get()));

  if (!sb_attach_info) {
    error = Status::FromErrorStringWithFormat(
        "Couldn't cast lldb::SBAttachInfo to lldb::ProcessAttachInfoSP.");
    return nullptr;
  }

  return m_interpreter.GetOpaqueTypeFromSBAttachInfo(*sb_attach_info);
}

template <>
lldb::ProcessLaunchInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject<
    lldb::ProcessLaunchInfoSP>(python::PythonObject &p, Status &error) {
  lldb::SBLaunchInfo *sb_launch_info = reinterpret_cast<lldb::SBLaunchInfo *>(
      python::LLDBSWIGPython_CastPyObjectToSBLaunchInfo(p.get()));

  if (!sb_launch_info) {
    error = Status::FromErrorStringWithFormat(
        "Couldn't cast lldb::SBLaunchInfo to lldb::ProcessLaunchInfoSP.");
    return nullptr;
  }

  return m_interpreter.GetOpaqueTypeFromSBLaunchInfo(*sb_launch_info);
}

template <>
std::optional<MemoryRegionInfo>
ScriptedPythonInterface::ExtractValueFromPythonObject<
    std::optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error) {

  lldb::SBMemoryRegionInfo *sb_mem_reg_info =
      reinterpret_cast<lldb::SBMemoryRegionInfo *>(
          python::LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(p.get()));

  if (!sb_mem_reg_info) {
    error = Status::FromErrorStringWithFormat(
        "Couldn't cast lldb::SBMemoryRegionInfo to "
        "lldb_private::MemoryRegionInfo.");
    return {};
  }

  return m_interpreter.GetOpaqueTypeFromSBMemoryRegionInfo(*sb_mem_reg_info);
}

template <>
lldb::ExecutionContextRefSP
ScriptedPythonInterface::ExtractValueFromPythonObject<
    lldb::ExecutionContextRefSP>(python::PythonObject &p, Status &error) {

  lldb::SBExecutionContext *sb_exe_ctx =
      reinterpret_cast<lldb::SBExecutionContext *>(
          python::LLDBSWIGPython_CastPyObjectToSBExecutionContext(p.get()));

  if (!sb_exe_ctx) {
    error = Status::FromErrorStringWithFormat(
        "Couldn't cast lldb::SBExecutionContext to "
        "lldb::ExecutionContextRefSP.");
    return {};
  }

  return m_interpreter.GetOpaqueTypeFromSBExecutionContext(*sb_exe_ctx);
}

template <>
lldb::DescriptionLevel
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DescriptionLevel>(
    python::PythonObject &p, Status &error) {
  lldb::DescriptionLevel ret_val = lldb::eDescriptionLevelBrief;
  llvm::Expected<unsigned long long> unsigned_or_err = p.AsUnsignedLongLong();
  if (!unsigned_or_err) {
    error = (Status::FromError(unsigned_or_err.takeError()));
    return ret_val;
  }
  unsigned long long unsigned_val = *unsigned_or_err;
  if (unsigned_val >= lldb::DescriptionLevel::kNumDescriptionLevels) {
    error = Status("value too large for lldb::DescriptionLevel.");
    return ret_val;
  }
  return static_cast<lldb::DescriptionLevel>(unsigned_val);
}

template <>
lldb::StackFrameListSP
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StackFrameListSP>(
    python::PythonObject &p, Status &error) {

  lldb::SBFrameList *sb_frame_list = reinterpret_cast<lldb::SBFrameList *>(
      python::LLDBSWIGPython_CastPyObjectToSBFrameList(p.get()));

  if (!sb_frame_list) {
    error = Status::FromErrorStringWithFormat(
        "couldn't cast lldb::SBFrameList to lldb::StackFrameListSP.");
    return {};
  }

  return m_interpreter.GetOpaqueTypeFromSBFrameList(*sb_frame_list);
}

template <>
lldb::ValueObjectSP
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::ValueObjectSP>(
    python::PythonObject &p, Status &error) {
  lldb::SBValue *sb_value = reinterpret_cast<lldb::SBValue *>(
      python::LLDBSWIGPython_CastPyObjectToSBValue(p.get()));
  if (!sb_value) {
    error = Status::FromErrorStringWithFormat(
        "couldn't cast lldb::SBValue to lldb::ValueObjectSP");
    return {};
  }

  return m_interpreter.GetOpaqueTypeFromSBValue(*sb_value);
}

template <>
lldb::TargetSP
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::TargetSP>(
    python::PythonObject &p, Status &error) {
  lldb::SBTarget *sb_target = reinterpret_cast<lldb::SBTarget *>(
      python::LLDBSWIGPython_CastPyObjectToSBTarget(p.get()));
  if (!sb_target) {
    error = Status::FromErrorStringWithFormat(
        "couldn't cast lldb::SBTarget to lldb::TargetSP");
    return {};
  }

  return m_interpreter.GetOpaqueTypeFromSBTarget(*sb_target);
}

template <>
lldb::ValueObjectListSP
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::ValueObjectListSP>(
    python::PythonObject &p, Status &error) {
  // Two Python return shapes are accepted here so callers can go through
  // Dispatch<ValueObjectListSP>() uniformly: an `SBValueList` wrapper
  // (what most extension methods return) and a plain Python `list` of
  // `SBValue` (what `get_recognized_arguments` is documented to return).
  lldb::ValueObjectListSP out = std::make_shared<ValueObjectList>();
  if (auto *sb_value_list = reinterpret_cast<lldb::SBValueList *>(
          python::LLDBSWIGPython_CastPyObjectToSBValueList(p.get()))) {
    for (uint32_t i = 0, e = sb_value_list->GetSize(); i < e; ++i) {
      SBValue value = sb_value_list->GetValueAtIndex(i);
      out->Append(m_interpreter.GetOpaqueTypeFromSBValue(value));
    }
    return out;
  }

  // Fallback: a plain Python `list` of `SBValue`. Round-trip through
  // `CreateStructuredObject` so we don't touch the `PyList_*` C API
  // directly; unknown-shape items surface as `StructuredData::Generic`
  // holding their opaque `PyObject*`, which we hand back to SWIG to
  // recover the SBValue wrapper.
  StructuredData::ObjectSP structured = p.CreateStructuredObject();
  StructuredData::Array *arr = structured ? structured->GetAsArray() : nullptr;
  if (arr) {
    size_t index = 0;
    bool aborted = false;
    arr->ForEach([&](StructuredData::Object *item) {
      StructuredData::Generic *generic = item ? item->GetAsGeneric() : nullptr;
      if (!generic) {
        error = Status::FromErrorStringWithFormatv(
            "ValueObjectList item at index {0} is not a "
            "StructuredData::Generic",
            index);
        aborted = true;
        return false;
      }
      auto *sb_value = reinterpret_cast<lldb::SBValue *>(
          python::LLDBSWIGPython_CastPyObjectToSBValue(
              static_cast<PyObject *>(generic->GetValue())));
      if (sb_value)
        if (auto valobj_sp = m_interpreter.GetOpaqueTypeFromSBValue(*sb_value))
          out->Append(valobj_sp);
      ++index;
      return true;
    });
    if (aborted)
      return {};
    return out;
  }

  error = Status::FromErrorStringWithFormat(
      "couldn't extract ValueObjectList from Python return value");
  return {};
}

template <>
std::optional<lldb::ValueType>
ScriptedPythonInterface::ExtractValueFromPythonObject<
    std::optional<lldb::ValueType>>(python::PythonObject &p, Status &error) {
  if (p.IsNone())
    return std::nullopt;

  llvm::Expected<unsigned long long> val = p.AsUnsignedLongLong();
  if (!val) {
    error = Status::FromError(val.takeError());
    return std::nullopt;
  }
  unsigned long long unmasked = *val & ~kValueTypeFlagsMask;
  unsigned long long flags = *val & kValueTypeFlagsMask;
  if (unmasked == eValueTypeInvalid || unmasked > kLastValueType) {
    error = Status::FromErrorStringWithFormatv(
        "value type invalid or too large (got {0} | {1:x})", unmasked, flags);
    return std::nullopt;
  }

  return static_cast<ValueType>(unmasked | flags);
}
