//===-- SBDeclaration.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 "lldb/API/SBDeclaration.h"
#include "SBReproducerPrivate.h"
#include "Utils.h"
#include "lldb/API/SBStream.h"
#include "lldb/Host/PosixApi.h"
#include "lldb/Symbol/Declaration.h"
#include "lldb/Utility/Stream.h"

#include <limits.h>

using namespace lldb;
using namespace lldb_private;

SBDeclaration::SBDeclaration() : m_opaque_up() {
  LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBDeclaration);
}

SBDeclaration::SBDeclaration(const SBDeclaration &rhs) : m_opaque_up() {
  LLDB_RECORD_CONSTRUCTOR(SBDeclaration, (const lldb::SBDeclaration &), rhs);

  m_opaque_up = clone(rhs.m_opaque_up);
}

SBDeclaration::SBDeclaration(const lldb_private::Declaration *lldb_object_ptr)
    : m_opaque_up() {
  if (lldb_object_ptr)
    m_opaque_up = std::make_unique<Declaration>(*lldb_object_ptr);
}

const SBDeclaration &SBDeclaration::operator=(const SBDeclaration &rhs) {
  LLDB_RECORD_METHOD(const lldb::SBDeclaration &,
                     SBDeclaration, operator=,(const lldb::SBDeclaration &),
                     rhs);

  if (this != &rhs)
    m_opaque_up = clone(rhs.m_opaque_up);
  return LLDB_RECORD_RESULT(*this);
}

void SBDeclaration::SetDeclaration(
    const lldb_private::Declaration &lldb_object_ref) {
  ref() = lldb_object_ref;
}

SBDeclaration::~SBDeclaration() {}

bool SBDeclaration::IsValid() const {
  LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBDeclaration, IsValid);
  return this->operator bool();
}
SBDeclaration::operator bool() const {
  LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBDeclaration, operator bool);

  return m_opaque_up.get() && m_opaque_up->IsValid();
}

SBFileSpec SBDeclaration::GetFileSpec() const {
  LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::SBFileSpec, SBDeclaration,
                                   GetFileSpec);


  SBFileSpec sb_file_spec;
  if (m_opaque_up.get() && m_opaque_up->GetFile())
    sb_file_spec.SetFileSpec(m_opaque_up->GetFile());


  return LLDB_RECORD_RESULT(sb_file_spec);
}

uint32_t SBDeclaration::GetLine() const {
  LLDB_RECORD_METHOD_CONST_NO_ARGS(uint32_t, SBDeclaration, GetLine);


  uint32_t line = 0;
  if (m_opaque_up)
    line = m_opaque_up->GetLine();


  return line;
}

uint32_t SBDeclaration::GetColumn() const {
  LLDB_RECORD_METHOD_CONST_NO_ARGS(uint32_t, SBDeclaration, GetColumn);

  if (m_opaque_up)
    return m_opaque_up->GetColumn();
  return 0;
}

void SBDeclaration::SetFileSpec(lldb::SBFileSpec filespec) {
  LLDB_RECORD_METHOD(void, SBDeclaration, SetFileSpec, (lldb::SBFileSpec),
                     filespec);

  if (filespec.IsValid())
    ref().SetFile(filespec.ref());
  else
    ref().SetFile(FileSpec());
}
void SBDeclaration::SetLine(uint32_t line) {
  LLDB_RECORD_METHOD(void, SBDeclaration, SetLine, (uint32_t), line);

  ref().SetLine(line);
}

void SBDeclaration::SetColumn(uint32_t column) {
  LLDB_RECORD_METHOD(void, SBDeclaration, SetColumn, (uint32_t), column);

  ref().SetColumn(column);
}

bool SBDeclaration::operator==(const SBDeclaration &rhs) const {
  LLDB_RECORD_METHOD_CONST(
      bool, SBDeclaration, operator==,(const lldb::SBDeclaration &), rhs);

  lldb_private::Declaration *lhs_ptr = m_opaque_up.get();
  lldb_private::Declaration *rhs_ptr = rhs.m_opaque_up.get();

  if (lhs_ptr && rhs_ptr)
    return lldb_private::Declaration::Compare(*lhs_ptr, *rhs_ptr) == 0;

  return lhs_ptr == rhs_ptr;
}

bool SBDeclaration::operator!=(const SBDeclaration &rhs) const {
  LLDB_RECORD_METHOD_CONST(
      bool, SBDeclaration, operator!=,(const lldb::SBDeclaration &), rhs);

  lldb_private::Declaration *lhs_ptr = m_opaque_up.get();
  lldb_private::Declaration *rhs_ptr = rhs.m_opaque_up.get();

  if (lhs_ptr && rhs_ptr)
    return lldb_private::Declaration::Compare(*lhs_ptr, *rhs_ptr) != 0;

  return lhs_ptr != rhs_ptr;
}

const lldb_private::Declaration *SBDeclaration::operator->() const {
  return m_opaque_up.get();
}

lldb_private::Declaration &SBDeclaration::ref() {
  if (m_opaque_up == nullptr)
    m_opaque_up.reset(new lldb_private::Declaration());
  return *m_opaque_up;
}

const lldb_private::Declaration &SBDeclaration::ref() const {
  return *m_opaque_up;
}

bool SBDeclaration::GetDescription(SBStream &description) {
  LLDB_RECORD_METHOD(bool, SBDeclaration, GetDescription, (lldb::SBStream &),
                     description);

  Stream &strm = description.ref();

  if (m_opaque_up) {
    char file_path[PATH_MAX * 2];
    m_opaque_up->GetFile().GetPath(file_path, sizeof(file_path));
    strm.Printf("%s:%u", file_path, GetLine());
    if (GetColumn() > 0)
      strm.Printf(":%u", GetColumn());
  } else
    strm.PutCString("No value");

  return true;
}

lldb_private::Declaration *SBDeclaration::get() { return m_opaque_up.get(); }

namespace lldb_private {
namespace repro {

template <>
void RegisterMethods<SBDeclaration>(Registry &R) {
  LLDB_REGISTER_CONSTRUCTOR(SBDeclaration, ());
  LLDB_REGISTER_CONSTRUCTOR(SBDeclaration, (const lldb::SBDeclaration &));
  LLDB_REGISTER_METHOD(
      const lldb::SBDeclaration &,
      SBDeclaration, operator=,(const lldb::SBDeclaration &));
  LLDB_REGISTER_METHOD_CONST(bool, SBDeclaration, IsValid, ());
  LLDB_REGISTER_METHOD_CONST(bool, SBDeclaration, operator bool, ());
  LLDB_REGISTER_METHOD_CONST(lldb::SBFileSpec, SBDeclaration, GetFileSpec,
                             ());
  LLDB_REGISTER_METHOD_CONST(uint32_t, SBDeclaration, GetLine, ());
  LLDB_REGISTER_METHOD_CONST(uint32_t, SBDeclaration, GetColumn, ());
  LLDB_REGISTER_METHOD(void, SBDeclaration, SetFileSpec, (lldb::SBFileSpec));
  LLDB_REGISTER_METHOD(void, SBDeclaration, SetLine, (uint32_t));
  LLDB_REGISTER_METHOD(void, SBDeclaration, SetColumn, (uint32_t));
  LLDB_REGISTER_METHOD_CONST(
      bool, SBDeclaration, operator==,(const lldb::SBDeclaration &));
  LLDB_REGISTER_METHOD_CONST(
      bool, SBDeclaration, operator!=,(const lldb::SBDeclaration &));
  LLDB_REGISTER_METHOD(bool, SBDeclaration, GetDescription,
                       (lldb::SBStream &));
}

}
}
