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

#ifndef __JSONGenerator_h_
#define __JSONGenerator_h_

// C Includes
// C++ Includes

#include <iomanip>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

//----------------------------------------------------------------------
/// @class JSONGenerator JSONGenerator.h
/// A class which can construct structured data for the sole purpose
/// of printing it in JSON format.
///
/// A stripped down version of lldb's StructuredData objects which are much
/// general purpose.  This variant is intended only for assembling information
/// and printing it as a JSON string.
//----------------------------------------------------------------------

class JSONGenerator {
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;

  enum class Type {
    eTypeInvalid = -1,
    eTypeNull = 0,
    eTypeGeneric,
    eTypeArray,
    eTypeInteger,
    eTypeFloat,
    eTypeBoolean,
    eTypeString,
    eTypeDictionary
  };

  class Object : public std::enable_shared_from_this<Object> {
  public:
    Object(Type t = Type::eTypeInvalid) : m_type(t) {}

    virtual ~Object() {}

    virtual bool IsValid() const { return true; }

    virtual void Clear() { m_type = Type::eTypeInvalid; }

    Type GetType() const { return m_type; }

    void SetType(Type t) { m_type = t; }

    Array *GetAsArray() {
      if (m_type == Type::eTypeArray)
        return (Array *)this;
      return NULL;
    }

    Dictionary *GetAsDictionary() {
      if (m_type == Type::eTypeDictionary)
        return (Dictionary *)this;
      return NULL;
    }

    Integer *GetAsInteger() {
      if (m_type == Type::eTypeInteger)
        return (Integer *)this;
      return NULL;
    }

    Float *GetAsFloat() {
      if (m_type == Type::eTypeFloat)
        return (Float *)this;
      return NULL;
    }

    Boolean *GetAsBoolean() {
      if (m_type == Type::eTypeBoolean)
        return (Boolean *)this;
      return NULL;
    }

    String *GetAsString() {
      if (m_type == Type::eTypeString)
        return (String *)this;
      return NULL;
    }

    Generic *GetAsGeneric() {
      if (m_type == Type::eTypeGeneric)
        return (Generic *)this;
      return NULL;
    }

    virtual void Dump(std::ostream &s) const = 0;

  private:
    Type m_type;
  };

  class Array : public Object {
  public:
    Array() : Object(Type::eTypeArray) {}

    virtual ~Array() {}

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

    void Dump(std::ostream &s) const override {
      s << "[";
      const size_t arrsize = m_items.size();
      for (size_t i = 0; i < arrsize; ++i) {
        m_items[i]->Dump(s);
        if (i + 1 < arrsize)
          s << ",";
      }
      s << "]";
    }

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

  class Integer : public Object {
  public:
    Integer(uint64_t value = 0) : Object(Type::eTypeInteger), m_value(value) {}

    virtual ~Integer() {}

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

    void Dump(std::ostream &s) const override { s << m_value; }

  protected:
    uint64_t m_value;
  };

  class Float : public Object {
  public:
    Float(double d = 0.0) : Object(Type::eTypeFloat), m_value(d) {}

    virtual ~Float() {}

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

    void Dump(std::ostream &s) const override { s << m_value; }

  protected:
    double m_value;
  };

  class Boolean : public Object {
  public:
    Boolean(bool b = false) : Object(Type::eTypeBoolean), m_value(b) {}

    virtual ~Boolean() {}

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

    void Dump(std::ostream &s) const override {
      if (m_value == true)
        s << "true";
      else
        s << "false";
    }

  protected:
    bool m_value;
  };

  class String : public Object {
  public:
    String() : Object(Type::eTypeString), m_value() {}

    String(const std::string &s) : Object(Type::eTypeString), m_value(s) {}

    String(const std::string &&s) : Object(Type::eTypeString), m_value(s) {}

    void SetValue(const std::string &string) { m_value = string; }

    void Dump(std::ostream &s) const override {
      std::string quoted;
      const size_t strsize = m_value.size();
      for (size_t i = 0; i < strsize; ++i) {
        char ch = m_value[i];
        if (ch == '"')
          quoted.push_back('\\');
        quoted.push_back(ch);
      }
      s << '"' << quoted.c_str() << '"';
    }

  protected:
    std::string m_value;
  };

  class Dictionary : public Object {
  public:
    Dictionary() : Object(Type::eTypeDictionary), m_dict() {}

    virtual ~Dictionary() {}

    void AddItem(std::string key, ObjectSP value) {
      m_dict.push_back(Pair(key, value));
    }

    void AddIntegerItem(std::string key, uint64_t value) {
      AddItem(key, ObjectSP(new Integer(value)));
    }

    void AddFloatItem(std::string key, double value) {
      AddItem(key, ObjectSP(new Float(value)));
    }

    void AddStringItem(std::string key, std::string value) {
      AddItem(key, ObjectSP(new String(std::move(value))));
    }

    void AddBytesAsHexASCIIString(std::string key, const uint8_t *src,
                                  size_t src_len) {
      if (src && src_len) {
        std::ostringstream strm;
        for (size_t i = 0; i < src_len; i++)
          strm << std::setfill('0') << std::hex << std::right << std::setw(2)
               << ((uint32_t)(src[i]));
        AddItem(key, ObjectSP(new String(std::move(strm.str()))));
      } else {
        AddItem(key, ObjectSP(new String()));
      }
    }

    void AddBooleanItem(std::string key, bool value) {
      AddItem(key, ObjectSP(new Boolean(value)));
    }

    void Dump(std::ostream &s) const override {
      bool have_printed_one_elem = false;
      s << "{";
      for (collection::const_iterator iter = m_dict.begin();
           iter != m_dict.end(); ++iter) {
        if (have_printed_one_elem == false) {
          have_printed_one_elem = true;
        } else {
          s << ",";
        }
        s << "\"" << iter->first.c_str() << "\":";
        iter->second->Dump(s);
      }
      s << "}";
    }

  protected:
    // Keep the dictionary as a vector so the dictionary doesn't reorder itself
    // when you dump it
    // We aren't accessing keys by name, so this won't affect performance
    typedef std::pair<std::string, ObjectSP> Pair;
    typedef std::vector<Pair> collection;
    collection m_dict;
  };

  class Null : public Object {
  public:
    Null() : Object(Type::eTypeNull) {}

    virtual ~Null() {}

    bool IsValid() const override { return false; }

    void Dump(std::ostream &s) const override { s << "null"; }

  protected:
  };

  class Generic : public Object {
  public:
    explicit Generic(void *object = nullptr)
        : Object(Type::eTypeGeneric), 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 Dump(std::ostream &s) const override;

  private:
    void *m_object;
  };

}; // class JSONGenerator

#endif // __JSONGenerator_h_
