//===-- TypeSummary.h -------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef lldb_TypeSummary_h_
#define lldb_TypeSummary_h_

// C Includes
#include <stdint.h>

// C++ Includes
#include <functional>
#include <memory>
#include <string>

// Other libraries and framework includes
// Project includes
#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(const TypeSummaryOptions &rhs);

  ~TypeSummaryOptions() = default;

  TypeSummaryOptions &operator=(const TypeSummaryOptions &rhs);

  lldb::LanguageType GetLanguage() const;

  lldb::TypeSummaryCapping GetCapping() const;

  TypeSummaryOptions &SetLanguage(lldb::LanguageType);

  TypeSummaryOptions &SetCapping(lldb::TypeSummaryCapping);

private:
  lldb::LanguageType m_lang;
  lldb::TypeSummaryCapping m_capping;
};

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

  virtual ~TypeSummaryImpl() = default;

  Kind GetKind() const { return m_kind; }

  class Flags {
  public:
    Flags() : m_flags(lldb::eTypeOptionCascade) {}

    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;
  };

  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;
  DISALLOW_COPY_AND_ASSIGN(TypeSummaryImpl);
};

// 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:
  DISALLOW_COPY_AND_ASSIGN(StringSummaryFormat);
};

// 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 = 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:
  DISALLOW_COPY_AND_ASSIGN(CXXFunctionSummaryFormat);
};

// 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:
  DISALLOW_COPY_AND_ASSIGN(ScriptSummaryFormat);
};
} // namespace lldb_private

#endif // lldb_TypeSummary_h_
