//===-- LibStdcppTuple.cpp --------------------------------------*- C++ -*-===//
//
// 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 "LibStdcpp.h"

#include "lldb/Core/ValueObject.h"
#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/DataFormatters/TypeSynthetic.h"
#include "lldb/Utility/ConstString.h"

#include <memory>
#include <vector>

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;

namespace {

class LibStdcppTupleSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
public:
  explicit LibStdcppTupleSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);

  size_t CalculateNumChildren() override;

  lldb::ValueObjectSP GetChildAtIndex(size_t idx) override;

  bool Update() override;

  bool MightHaveChildren() override;

  size_t GetIndexOfChildWithName(ConstString name) override;

private:
  std::vector<ValueObjectSP> m_members;
};

} // end of anonymous namespace

LibStdcppTupleSyntheticFrontEnd::LibStdcppTupleSyntheticFrontEnd(
    lldb::ValueObjectSP valobj_sp)
    : SyntheticChildrenFrontEnd(*valobj_sp) {
  Update();
}

bool LibStdcppTupleSyntheticFrontEnd::Update() {
  m_members.clear();

  ValueObjectSP valobj_backend_sp = m_backend.GetSP();
  if (!valobj_backend_sp)
    return false;

  ValueObjectSP next_child_sp = valobj_backend_sp->GetNonSyntheticValue();
  while (next_child_sp != nullptr) {
    ValueObjectSP current_child = next_child_sp;
    next_child_sp = nullptr;

    size_t child_count = current_child->GetNumChildren();
    for (size_t i = 0; i < child_count; ++i) {
      ValueObjectSP child_sp = current_child->GetChildAtIndex(i, true);
      llvm::StringRef name_str = child_sp->GetName().GetStringRef();
      if (name_str.startswith("std::_Tuple_impl<")) {
        next_child_sp = child_sp;
      } else if (name_str.startswith("std::_Head_base<")) {
        ValueObjectSP value_sp =
            child_sp->GetChildMemberWithName(ConstString("_M_head_impl"), true);
        if (value_sp) {
          StreamString name;
          name.Printf("[%zd]", m_members.size());
          m_members.push_back(value_sp->Clone(ConstString(name.GetString())));
        }
      }
    }
  }

  return false;
}

bool LibStdcppTupleSyntheticFrontEnd::MightHaveChildren() { return true; }

lldb::ValueObjectSP
LibStdcppTupleSyntheticFrontEnd::GetChildAtIndex(size_t idx) {
  if (idx < m_members.size())
    return m_members[idx];
  return lldb::ValueObjectSP();
}

size_t LibStdcppTupleSyntheticFrontEnd::CalculateNumChildren() {
  return m_members.size();
}

size_t LibStdcppTupleSyntheticFrontEnd::GetIndexOfChildWithName(
    ConstString name) {
  return ExtractIndexFromString(name.GetCString());
}

SyntheticChildrenFrontEnd *
lldb_private::formatters::LibStdcppTupleSyntheticFrontEndCreator(
    CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
  return (valobj_sp ? new LibStdcppTupleSyntheticFrontEnd(valobj_sp) : nullptr);
}
