//===-- StructuredData.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_UTILITY_STRUCTUREDDATA_H
#define LLDB_UTILITY_STRUCTUREDDATA_H

#include "llvm/ADT/StringRef.h"
#include "llvm/Support/JSON.h"

#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Stream.h"
#include "lldb/lldb-enumerations.h"

#include <cassert>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <map>
#include <memory>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>

namespace lldb_private {
class Status;
}

namespace lldb_private {

/// \class StructuredData StructuredData.h "lldb/Utility/StructuredData.h"
/// A class which can hold structured data
///
/// The StructuredData class is designed to hold the data from a JSON or plist
/// style file -- a serialized data structure with dictionaries (maps,
/// hashes), arrays, and concrete values like integers, floating point
/// numbers, strings, booleans.
///
/// StructuredData does not presuppose any knowledge of the schema for the
/// data it is holding; it can parse JSON data, for instance, and other parts
/// of lldb can iterate through the parsed data set to find keys and values
/// that may be present.

class StructuredData {
public:
  class Object;
  class Array;
  class Integer;
  class Float;
  class Boolean;
  class String;
  class Dictionary;
  class Generic;

  typedef std::shared_ptr<Object> ObjectSP;
  typedef std::shared_ptr<Array> ArraySP;
  typedef std::shared_ptr<Integer> IntegerSP;
  typedef std::shared_ptr<Float> FloatSP;
  typedef std::shared_ptr<Boolean> BooleanSP;
  typedef std::shared_ptr<String> StringSP;
  typedef std::shared_ptr<Dictionary> DictionarySP;
  typedef std::shared_ptr<Generic> GenericSP;

  class Object : public std::enable_shared_from_this<Object> {
  public:
    Object(lldb::StructuredDataType t = lldb::eStructuredDataTypeInvalid)
        : m_type(t) {}

    virtual ~Object() = default;

    virtual bool IsValid() const { return true; }

    virtual void Clear() { m_type = lldb::eStructuredDataTypeInvalid; }

    lldb::StructuredDataType GetType() const { return m_type; }

    void SetType(lldb::StructuredDataType t) { m_type = t; }

    Array *GetAsArray() {
      return ((m_type == lldb::eStructuredDataTypeArray)
                  ? static_cast<Array *>(this)
                  : nullptr);
    }

    Dictionary *GetAsDictionary() {
      return ((m_type == lldb::eStructuredDataTypeDictionary)
                  ? static_cast<Dictionary *>(this)
                  : nullptr);
    }

    Integer *GetAsInteger() {
      return ((m_type == lldb::eStructuredDataTypeInteger)
                  ? static_cast<Integer *>(this)
                  : nullptr);
    }

    uint64_t GetIntegerValue(uint64_t fail_value = 0) {
      Integer *integer = GetAsInteger();
      return ((integer != nullptr) ? integer->GetValue() : fail_value);
    }

    Float *GetAsFloat() {
      return ((m_type == lldb::eStructuredDataTypeFloat)
                  ? static_cast<Float *>(this)
                  : nullptr);
    }

    double GetFloatValue(double fail_value = 0.0) {
      Float *f = GetAsFloat();
      return ((f != nullptr) ? f->GetValue() : fail_value);
    }

    Boolean *GetAsBoolean() {
      return ((m_type == lldb::eStructuredDataTypeBoolean)
                  ? static_cast<Boolean *>(this)
                  : nullptr);
    }

    bool GetBooleanValue(bool fail_value = false) {
      Boolean *b = GetAsBoolean();
      return ((b != nullptr) ? b->GetValue() : fail_value);
    }

    String *GetAsString() {
      return ((m_type == lldb::eStructuredDataTypeString)
                  ? static_cast<String *>(this)
                  : nullptr);
    }

    llvm::StringRef GetStringValue(const char *fail_value = nullptr) {
      String *s = GetAsString();
      if (s)
        return s->GetValue();

      return fail_value;
    }

    Generic *GetAsGeneric() {
      return ((m_type == lldb::eStructuredDataTypeGeneric)
                  ? static_cast<Generic *>(this)
                  : nullptr);
    }

    ObjectSP GetObjectForDotSeparatedPath(llvm::StringRef path);

    void DumpToStdout(bool pretty_print = true) const;

    virtual void Serialize(llvm::json::OStream &s) const = 0;

    void Dump(lldb_private::Stream &s, bool pretty_print = true) const {
      llvm::json::OStream jso(s.AsRawOstream(), pretty_print ? 2 : 0);
      Serialize(jso);
    }

  private:
    lldb::StructuredDataType m_type;
  };

  class Array : public Object {
  public:
    Array() : Object(lldb::eStructuredDataTypeArray) {}

    ~Array() override = default;

    bool
    ForEach(std::function<bool(Object *object)> const &foreach_callback) const {
      for (const auto &object_sp : m_items) {
        if (!foreach_callback(object_sp.get()))
          return false;
      }
      return true;
    }

    size_t GetSize() const { return m_items.size(); }

    ObjectSP operator[](size_t idx) {
      if (idx < m_items.size())
        return m_items[idx];
      return ObjectSP();
    }

    ObjectSP GetItemAtIndex(size_t idx) const {
      assert(idx < GetSize());
      if (idx < m_items.size())
        return m_items[idx];
      return ObjectSP();
    }

    template <class IntType>
    bool GetItemAtIndexAsInteger(size_t idx, IntType &result) const {
      ObjectSP value_sp = GetItemAtIndex(idx);
      if (value_sp.get()) {
        if (auto int_value = value_sp->GetAsInteger()) {
          result = static_cast<IntType>(int_value->GetValue());
          return true;
        }
      }
      return false;
    }

    template <class IntType>
    bool GetItemAtIndexAsInteger(size_t idx, IntType &result,
                                 IntType default_val) const {
      bool success = GetItemAtIndexAsInteger(idx, result);
      if (!success)
        result = default_val;
      return success;
    }

    bool GetItemAtIndexAsString(size_t idx, llvm::StringRef &result) const {
      ObjectSP value_sp = GetItemAtIndex(idx);
      if (value_sp.get()) {
        if (auto string_value = value_sp->GetAsString()) {
          result = string_value->GetValue();
          return true;
        }
      }
      return false;
    }

    bool GetItemAtIndexAsString(size_t idx, llvm::StringRef &result,
                                llvm::StringRef default_val) const {
      bool success = GetItemAtIndexAsString(idx, result);
      if (!success)
        result = default_val;
      return success;
    }

    bool GetItemAtIndexAsString(size_t idx, ConstString &result) const {
      ObjectSP value_sp = GetItemAtIndex(idx);
      if (value_sp.get()) {
        if (auto string_value = value_sp->GetAsString()) {
          result = ConstString(string_value->GetValue());
          return true;
        }
      }
      return false;
    }

    bool GetItemAtIndexAsString(size_t idx, ConstString &result,
                                const char *default_val) const {
      bool success = GetItemAtIndexAsString(idx, result);
      if (!success)
        result.SetCString(default_val);
      return success;
    }

    bool GetItemAtIndexAsDictionary(size_t idx, Dictionary *&result) const {
      result = nullptr;
      ObjectSP value_sp = GetItemAtIndex(idx);
      if (value_sp.get()) {
        result = value_sp->GetAsDictionary();
        return (result != nullptr);
      }
      return false;
    }

    bool GetItemAtIndexAsArray(size_t idx, Array *&result) const {
      result = nullptr;
      ObjectSP value_sp = GetItemAtIndex(idx);
      if (value_sp.get()) {
        result = value_sp->GetAsArray();
        return (result != nullptr);
      }
      return false;
    }

    void Push(const ObjectSP &item) { m_items.push_back(item); }

    void AddItem(const ObjectSP &item) { m_items.push_back(item); }

    void Serialize(llvm::json::OStream &s) const override;

  protected:
    typedef std::vector<ObjectSP> collection;
    collection m_items;
  };

  class Integer : public Object {
  public:
    Integer(uint64_t i = 0)
        : Object(lldb::eStructuredDataTypeInteger), m_value(i) {}

    ~Integer() override = default;

    void SetValue(uint64_t value) { m_value = value; }

    uint64_t GetValue() { return m_value; }

    void Serialize(llvm::json::OStream &s) const override;

  protected:
    uint64_t m_value;
  };

  class Float : public Object {
  public:
    Float(double d = 0.0)
        : Object(lldb::eStructuredDataTypeFloat), m_value(d) {}

    ~Float() override = default;

    void SetValue(double value) { m_value = value; }

    double GetValue() { return m_value; }

    void Serialize(llvm::json::OStream &s) const override;

  protected:
    double m_value;
  };

  class Boolean : public Object {
  public:
    Boolean(bool b = false)
        : Object(lldb::eStructuredDataTypeBoolean), m_value(b) {}

    ~Boolean() override = default;

    void SetValue(bool value) { m_value = value; }

    bool GetValue() { return m_value; }

    void Serialize(llvm::json::OStream &s) const override;

  protected:
    bool m_value;
  };

  class String : public Object {
  public:
    String() : Object(lldb::eStructuredDataTypeString) {}
    explicit String(llvm::StringRef S)
        : Object(lldb::eStructuredDataTypeString), m_value(S) {}

    void SetValue(llvm::StringRef S) { m_value = std::string(S); }

    llvm::StringRef GetValue() { return m_value; }

    void Serialize(llvm::json::OStream &s) const override;

  protected:
    std::string m_value;
  };

  class Dictionary : public Object {
  public:
    Dictionary() : Object(lldb::eStructuredDataTypeDictionary) {}

    Dictionary(ObjectSP obj_sp) : Object(lldb::eStructuredDataTypeDictionary) {
      if (!obj_sp || obj_sp->GetType() != lldb::eStructuredDataTypeDictionary) {
        SetType(lldb::eStructuredDataTypeInvalid);
        return;
      }

      Dictionary *dict = obj_sp->GetAsDictionary();
      m_dict = dict->m_dict;
    }

    ~Dictionary() override = default;

    size_t GetSize() const { return m_dict.size(); }

    void ForEach(std::function<bool(ConstString key, Object *object)> const
                     &callback) const {
      for (const auto &pair : m_dict) {
        if (!callback(pair.first, pair.second.get()))
          break;
      }
    }

    ArraySP GetKeys() const {
      auto array_sp = std::make_shared<Array>();
      collection::const_iterator iter;
      for (iter = m_dict.begin(); iter != m_dict.end(); ++iter) {
        auto key_object_sp = std::make_shared<String>();
        key_object_sp->SetValue(iter->first.AsCString());
        array_sp->Push(key_object_sp);
      }
      return array_sp;
    }

    ObjectSP GetValueForKey(llvm::StringRef key) const {
      ObjectSP value_sp;
      if (!key.empty()) {
        ConstString key_cs(key);
        collection::const_iterator iter = m_dict.find(key_cs);
        if (iter != m_dict.end())
          value_sp = iter->second;
      }
      return value_sp;
    }

    bool GetValueForKeyAsBoolean(llvm::StringRef key, bool &result) const {
      bool success = false;
      ObjectSP value_sp = GetValueForKey(key);
      if (value_sp.get()) {
        Boolean *result_ptr = value_sp->GetAsBoolean();
        if (result_ptr) {
          result = result_ptr->GetValue();
          success = true;
        }
      }
      return success;
    }
    template <class IntType>
    bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result) const {
      ObjectSP value_sp = GetValueForKey(key);
      if (value_sp) {
        if (auto int_value = value_sp->GetAsInteger()) {
          result = static_cast<IntType>(int_value->GetValue());
          return true;
        }
      }
      return false;
    }

    template <class IntType>
    bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result,
                                 IntType default_val) const {
      bool success = GetValueForKeyAsInteger<IntType>(key, result);
      if (!success)
        result = default_val;
      return success;
    }

    bool GetValueForKeyAsString(llvm::StringRef key,
                                llvm::StringRef &result) const {
      ObjectSP value_sp = GetValueForKey(key);
      if (value_sp.get()) {
        if (auto string_value = value_sp->GetAsString()) {
          result = string_value->GetValue();
          return true;
        }
      }
      return false;
    }

    bool GetValueForKeyAsString(llvm::StringRef key, llvm::StringRef &result,
                                const char *default_val) const {
      bool success = GetValueForKeyAsString(key, result);
      if (!success) {
        if (default_val)
          result = default_val;
        else
          result = llvm::StringRef();
      }
      return success;
    }

    bool GetValueForKeyAsString(llvm::StringRef key,
                                ConstString &result) const {
      ObjectSP value_sp = GetValueForKey(key);
      if (value_sp.get()) {
        if (auto string_value = value_sp->GetAsString()) {
          result = ConstString(string_value->GetValue());
          return true;
        }
      }
      return false;
    }

    bool GetValueForKeyAsString(llvm::StringRef key, ConstString &result,
                                const char *default_val) const {
      bool success = GetValueForKeyAsString(key, result);
      if (!success)
        result.SetCString(default_val);
      return success;
    }

    bool GetValueForKeyAsDictionary(llvm::StringRef key,
                                    Dictionary *&result) const {
      result = nullptr;
      ObjectSP value_sp = GetValueForKey(key);
      if (value_sp.get()) {
        result = value_sp->GetAsDictionary();
        return (result != nullptr);
      }
      return false;
    }

    bool GetValueForKeyAsArray(llvm::StringRef key, Array *&result) const {
      result = nullptr;
      ObjectSP value_sp = GetValueForKey(key);
      if (value_sp.get()) {
        result = value_sp->GetAsArray();
        return (result != nullptr);
      }
      return false;
    }

    bool HasKey(llvm::StringRef key) const {
      ConstString key_cs(key);
      collection::const_iterator search = m_dict.find(key_cs);
      return search != m_dict.end();
    }

    void AddItem(llvm::StringRef key, ObjectSP value_sp) {
      ConstString key_cs(key);
      m_dict[key_cs] = std::move(value_sp);
    }

    void AddIntegerItem(llvm::StringRef key, uint64_t value) {
      AddItem(key, std::make_shared<Integer>(value));
    }

    void AddFloatItem(llvm::StringRef key, double value) {
      AddItem(key, std::make_shared<Float>(value));
    }

    void AddStringItem(llvm::StringRef key, llvm::StringRef value) {
      AddItem(key, std::make_shared<String>(std::move(value)));
    }

    void AddBooleanItem(llvm::StringRef key, bool value) {
      AddItem(key, std::make_shared<Boolean>(value));
    }

    void Serialize(llvm::json::OStream &s) const override;

  protected:
    typedef std::map<ConstString, ObjectSP> collection;
    collection m_dict;
  };

  class Null : public Object {
  public:
    Null() : Object(lldb::eStructuredDataTypeNull) {}

    ~Null() override = default;

    bool IsValid() const override { return false; }

    void Serialize(llvm::json::OStream &s) const override;
  };

  class Generic : public Object {
  public:
    explicit Generic(void *object = nullptr)
        : Object(lldb::eStructuredDataTypeGeneric), m_object(object) {}

    void SetValue(void *value) { m_object = value; }

    void *GetValue() const { return m_object; }

    bool IsValid() const override { return m_object != nullptr; }

    void Serialize(llvm::json::OStream &s) const override;

  private:
    void *m_object;
  };

  static ObjectSP ParseJSON(const std::string &json_text);
  static ObjectSP ParseJSONFromFile(const FileSpec &file, Status &error);
};

} // namespace lldb_private

#endif // LLDB_UTILITY_STRUCTUREDDATA_H
