//===-- TypeSummary.h -------------------------------------------*- 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
//
//===----------------------------------------------------------------------===//

#ifndef LLDB_DATAFORMATTERS_TYPESUMMARY_H
#define LLDB_DATAFORMATTERS_TYPESUMMARY_H

#include <cstdint>

#include <functional>
#include <memory>
#include <string>

#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-public.h"

#include "lldb/Core/FormatEntity.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StructuredData.h"

namespace lldb_private {
class TypeSummaryOptions {
public:
  TypeSummaryOptions();

  ~TypeSummaryOptions() = default;

  lldb::LanguageType GetLanguage() const;

  lldb::TypeSummaryCapping GetCapping() const;

  TypeSummaryOptions &SetLanguage(lldb::LanguageType);

  TypeSummaryOptions &SetCapping(lldb::TypeSummaryCapping);

private:
  lldb::LanguageType m_lang = lldb::eLanguageTypeUnknown;
  lldb::TypeSummaryCapping m_capping = lldb::eTypeSummaryCapped;
};

class TypeSummaryImpl {
public:
  enum class Kind { eSummaryString, eScript, eCallback, eInternal };

  virtual ~TypeSummaryImpl() = default;

  Kind GetKind() const { return m_kind; }

  class Flags {
  public:
    Flags() = default;

    Flags(const Flags &other) : m_flags(other.m_flags) {}

    Flags(uint32_t value) : m_flags(value) {}

    Flags &operator=(const Flags &rhs) {
      if (&rhs != this)
        m_flags = rhs.m_flags;

      return *this;
    }

    Flags &operator=(const uint32_t &rhs) {
      m_flags = rhs;
      return *this;
    }

    Flags &Clear() {
      m_flags = 0;
      return *this;
    }

    bool GetCascades() const {
      return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade;
    }

    Flags &SetCascades(bool value = true) {
      if (value)
        m_flags |= lldb::eTypeOptionCascade;
      else
        m_flags &= ~lldb::eTypeOptionCascade;
      return *this;
    }

    bool GetSkipPointers() const {
      return (m_flags & lldb::eTypeOptionSkipPointers) ==
             lldb::eTypeOptionSkipPointers;
    }

    Flags &SetSkipPointers(bool value = true) {
      if (value)
        m_flags |= lldb::eTypeOptionSkipPointers;
      else
        m_flags &= ~lldb::eTypeOptionSkipPointers;
      return *this;
    }

    bool GetSkipReferences() const {
      return (m_flags & lldb::eTypeOptionSkipReferences) ==
             lldb::eTypeOptionSkipReferences;
    }

    Flags &SetSkipReferences(bool value = true) {
      if (value)
        m_flags |= lldb::eTypeOptionSkipReferences;
      else
        m_flags &= ~lldb::eTypeOptionSkipReferences;
      return *this;
    }

    bool GetDontShowChildren() const {
      return (m_flags & lldb::eTypeOptionHideChildren) ==
             lldb::eTypeOptionHideChildren;
    }

    Flags &SetDontShowChildren(bool value = true) {
      if (value)
        m_flags |= lldb::eTypeOptionHideChildren;
      else
        m_flags &= ~lldb::eTypeOptionHideChildren;
      return *this;
    }

    bool GetHideEmptyAggregates() const {
      return (m_flags & lldb::eTypeOptionHideEmptyAggregates) ==
             lldb::eTypeOptionHideEmptyAggregates;
    }

    Flags &SetHideEmptyAggregates(bool value = true) {
      if (value)
        m_flags |= lldb::eTypeOptionHideEmptyAggregates;
      else
        m_flags &= ~lldb::eTypeOptionHideEmptyAggregates;
      return *this;
    }

    bool GetDontShowValue() const {
      return (m_flags & lldb::eTypeOptionHideValue) ==
             lldb::eTypeOptionHideValue;
    }

    Flags &SetDontShowValue(bool value = true) {
      if (value)
        m_flags |= lldb::eTypeOptionHideValue;
      else
        m_flags &= ~lldb::eTypeOptionHideValue;
      return *this;
    }

    bool GetShowMembersOneLiner() const {
      return (m_flags & lldb::eTypeOptionShowOneLiner) ==
             lldb::eTypeOptionShowOneLiner;
    }

    Flags &SetShowMembersOneLiner(bool value = true) {
      if (value)
        m_flags |= lldb::eTypeOptionShowOneLiner;
      else
        m_flags &= ~lldb::eTypeOptionShowOneLiner;
      return *this;
    }

    bool GetHideItemNames() const {
      return (m_flags & lldb::eTypeOptionHideNames) ==
             lldb::eTypeOptionHideNames;
    }

    Flags &SetHideItemNames(bool value = true) {
      if (value)
        m_flags |= lldb::eTypeOptionHideNames;
      else
        m_flags &= ~lldb::eTypeOptionHideNames;
      return *this;
    }

    bool GetNonCacheable() const {
      return (m_flags & lldb::eTypeOptionNonCacheable) ==
             lldb::eTypeOptionNonCacheable;
    }

    Flags &SetNonCacheable(bool value = true) {
      if (value)
        m_flags |= lldb::eTypeOptionNonCacheable;
      else
        m_flags &= ~lldb::eTypeOptionNonCacheable;
      return *this;
    }

    uint32_t GetValue() { return m_flags; }

    void SetValue(uint32_t value) { m_flags = value; }

  private:
    uint32_t m_flags = lldb::eTypeOptionCascade;
  };

  bool Cascades() const { return m_flags.GetCascades(); }

  bool SkipsPointers() const { return m_flags.GetSkipPointers(); }

  bool SkipsReferences() const { return m_flags.GetSkipReferences(); }

  bool NonCacheable() const { return m_flags.GetNonCacheable(); }

  virtual bool DoesPrintChildren(ValueObject *valobj) const {
    return !m_flags.GetDontShowChildren();
  }

  virtual bool DoesPrintEmptyAggregates() const {
    return !m_flags.GetHideEmptyAggregates();
  }

  virtual bool DoesPrintValue(ValueObject *valobj) const {
    return !m_flags.GetDontShowValue();
  }

  bool IsOneLiner() const { return m_flags.GetShowMembersOneLiner(); }

  virtual bool HideNames(ValueObject *valobj) const {
    return m_flags.GetHideItemNames();
  }

  void SetCascades(bool value) { m_flags.SetCascades(value); }

  void SetSkipsPointers(bool value) { m_flags.SetSkipPointers(value); }

  void SetSkipsReferences(bool value) { m_flags.SetSkipReferences(value); }

  virtual void SetDoesPrintChildren(bool value) {
    m_flags.SetDontShowChildren(!value);
  }

  virtual void SetDoesPrintValue(bool value) {
    m_flags.SetDontShowValue(!value);
  }

  void SetIsOneLiner(bool value) { m_flags.SetShowMembersOneLiner(value); }

  virtual void SetHideNames(bool value) { m_flags.SetHideItemNames(value); }

  virtual void SetNonCacheable(bool value) { m_flags.SetNonCacheable(value); }

  uint32_t GetOptions() { return m_flags.GetValue(); }

  void SetOptions(uint32_t value) { m_flags.SetValue(value); }

  // we are using a ValueObject* instead of a ValueObjectSP because we do not
  // need to hold on to this for extended periods of time and we trust the
  // ValueObject to stay around for as long as it is required for us to
  // generate its summary
  virtual bool FormatObject(ValueObject *valobj, std::string &dest,
                            const TypeSummaryOptions &options) = 0;

  virtual std::string GetDescription() = 0;

  uint32_t &GetRevision() { return m_my_revision; }

  typedef std::shared_ptr<TypeSummaryImpl> SharedPointer;

protected:
  uint32_t m_my_revision;
  Flags m_flags;

  TypeSummaryImpl(Kind kind, const TypeSummaryImpl::Flags &flags);

private:
  Kind m_kind;
  TypeSummaryImpl(const TypeSummaryImpl &) = delete;
  const TypeSummaryImpl &operator=(const TypeSummaryImpl &) = delete;
};

// simple string-based summaries, using ${var to show data
struct StringSummaryFormat : public TypeSummaryImpl {
  std::string m_format_str;
  FormatEntity::Entry m_format;
  Status m_error;

  StringSummaryFormat(const TypeSummaryImpl::Flags &flags, const char *f);

  ~StringSummaryFormat() override = default;

  const char *GetSummaryString() const { return m_format_str.c_str(); }

  void SetSummaryString(const char *f);

  bool FormatObject(ValueObject *valobj, std::string &dest,
                    const TypeSummaryOptions &options) override;

  std::string GetDescription() override;

  static bool classof(const TypeSummaryImpl *S) {
    return S->GetKind() == Kind::eSummaryString;
  }

private:
  StringSummaryFormat(const StringSummaryFormat &) = delete;
  const StringSummaryFormat &operator=(const StringSummaryFormat &) = delete;
};

// summaries implemented via a C++ function
struct CXXFunctionSummaryFormat : public TypeSummaryImpl {
  // we should convert these to SBValue and SBStream if we ever cross the
  // boundary towards the external world
  typedef std::function<bool(ValueObject &, Stream &,
                             const TypeSummaryOptions &)>
      Callback;

  Callback m_impl;
  std::string m_description;

  CXXFunctionSummaryFormat(const TypeSummaryImpl::Flags &flags, Callback impl,
                           const char *description);

  ~CXXFunctionSummaryFormat() override = default;

  Callback GetBackendFunction() const { return m_impl; }

  const char *GetTextualInfo() const { return m_description.c_str(); }

  void SetBackendFunction(Callback cb_func) { m_impl = std::move(cb_func); }

  void SetTextualInfo(const char *descr) {
    if (descr)
      m_description.assign(descr);
    else
      m_description.clear();
  }

  bool FormatObject(ValueObject *valobj, std::string &dest,
                    const TypeSummaryOptions &options) override;

  std::string GetDescription() override;

  static bool classof(const TypeSummaryImpl *S) {
    return S->GetKind() == Kind::eCallback;
  }

  typedef std::shared_ptr<CXXFunctionSummaryFormat> SharedPointer;

private:
  CXXFunctionSummaryFormat(const CXXFunctionSummaryFormat &) = delete;
  const CXXFunctionSummaryFormat &
  operator=(const CXXFunctionSummaryFormat &) = delete;
};

// Python-based summaries, running script code to show data
struct ScriptSummaryFormat : public TypeSummaryImpl {
  std::string m_function_name;
  std::string m_python_script;
  StructuredData::ObjectSP m_script_function_sp;

  ScriptSummaryFormat(const TypeSummaryImpl::Flags &flags,
                      const char *function_name,
                      const char *python_script = nullptr);

  ~ScriptSummaryFormat() override = default;

  const char *GetFunctionName() const { return m_function_name.c_str(); }

  const char *GetPythonScript() const { return m_python_script.c_str(); }

  void SetFunctionName(const char *function_name) {
    if (function_name)
      m_function_name.assign(function_name);
    else
      m_function_name.clear();
    m_python_script.clear();
  }

  void SetPythonScript(const char *script) {
    if (script)
      m_python_script.assign(script);
    else
      m_python_script.clear();
  }

  bool FormatObject(ValueObject *valobj, std::string &dest,
                    const TypeSummaryOptions &options) override;

  std::string GetDescription() override;

  static bool classof(const TypeSummaryImpl *S) {
    return S->GetKind() == Kind::eScript;
  }

  typedef std::shared_ptr<ScriptSummaryFormat> SharedPointer;

private:
  ScriptSummaryFormat(const ScriptSummaryFormat &) = delete;
  const ScriptSummaryFormat &operator=(const ScriptSummaryFormat &) = delete;
};
} // namespace lldb_private

#endif // LLDB_DATAFORMATTERS_TYPESUMMARY_H
