/*
 * Copyright (C) 2009 Google Inc. All rights reserved.
 * Copyright (C) 2014 University of Washington. All rights reserved.
 * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include <wtf/HashMap.h>
#include <wtf/text/StringHash.h>
#include <wtf/text/WTFString.h>

namespace WTF {

// Make sure compiled symbols contain the WTF namespace prefix, but
// use a different inner namespace name so that JSON::Value is not ambigious.
// Otherwise, the compiler would have both WTF::JSON::Value and JSON::Value
// in scope and client code would have to use WTF::JSON::Value, which is tedious.
namespace JSONImpl {

class Array;
class ArrayBase;
class Object;
class ObjectBase;

// FIXME: unify this JSON parser with JSONParse in JavaScriptCore.
class WTF_EXPORT_PRIVATE Value : public RefCounted<Value> {
public:
    static constexpr int maxDepth = 1000;

    virtual ~Value()
    {
        switch (m_type) {
        case Type::Null:
        case Type::Boolean:
        case Type::Double:
        case Type::Integer:
            break;
        case Type::String:
            if (m_value.string)
                m_value.string->deref();
            break;
        case Type::Object:
        case Type::Array:
            break;
        }
    }

    static Ref<Value> null();
    static Ref<Value> create(bool);
    static Ref<Value> create(int);
    static Ref<Value> create(double);
    static Ref<Value> create(const String&);
    static Ref<Value> create(const char*);

    enum class Type {
        Null = 0,
        Boolean,
        Double,
        Integer,
        String,
        Object,
        Array,
    };

    Type type() const { return m_type; }
    bool isNull() const { return m_type == Type::Null; }

    bool asBoolean(bool&) const;
    bool asInteger(int&) const;
    bool asInteger(unsigned&) const;
    bool asInteger(long&) const;
    bool asInteger(long long&) const;
    bool asInteger(unsigned long&) const;
    bool asInteger(unsigned long long&) const;
    bool asDouble(double&) const;
    bool asDouble(float&) const;
    bool asString(String&) const;
    bool asValue(RefPtr<Value>&);

    virtual bool asObject(RefPtr<Object>&);
    virtual bool asArray(RefPtr<Array>&);

    static bool parseJSON(const String& jsonInput, RefPtr<Value>& output);

    String toJSONString() const;
    virtual void writeJSON(StringBuilder& output) const;

    virtual size_t memoryCost() const;

protected:
    Value()
        : m_type { Type::Null }
    {
    }

    explicit Value(Type type)
        : m_type(type)
    {
    }

    explicit Value(bool value)
        : m_type { Type::Boolean }
    {
        m_value.boolean = value;
    }

    explicit Value(int value)
        : m_type { Type::Integer }
    {
        m_value.number = static_cast<double>(value);
    }

    explicit Value(double value)
        : m_type(Type::Double)
    {
        m_value.number = value;
    }

    explicit Value(const String& value)
        : m_type { Type::String }
    {
        m_value.string = value.impl();
        if (m_value.string)
            m_value.string->ref();
    }

    explicit Value(const char* value)
        : m_type { Type::String }
    {
        String wrapper(value);
        m_value.string = wrapper.impl();
        if (m_value.string)
            m_value.string->ref();
    }

private:
    Type m_type { Type::Null };
    union {
        bool boolean;
        double number;
        StringImpl* string;
    } m_value;
};

class WTF_EXPORT_PRIVATE ObjectBase : public Value {
private:
    typedef HashMap<String, RefPtr<Value>> Dictionary;

public:
    typedef Dictionary::iterator iterator;
    typedef Dictionary::const_iterator const_iterator;

    Object* openAccessors();

    size_t memoryCost() const final;

protected:
    virtual ~ObjectBase();

    bool asObject(RefPtr<Object>& output) override;

    // FIXME: use templates to reduce the amount of duplicated set*() methods.
    void setBoolean(const String& name, bool);
    void setInteger(const String& name, int);
    void setDouble(const String& name, double);
    void setString(const String& name, const String&);
    void setValue(const String& name, RefPtr<Value>&&);
    void setObject(const String& name, RefPtr<ObjectBase>&&);
    void setArray(const String& name, RefPtr<ArrayBase>&&);

    iterator find(const String& name);
    const_iterator find(const String& name) const;

    // FIXME: use templates to reduce the amount of duplicated get*() methods.
    bool getBoolean(const String& name, bool& output) const;
    template<class T> bool getDouble(const String& name, T& output) const
    {
        RefPtr<Value> value;
        if (!getValue(name, value))
            return false;

        return value->asDouble(output);
    }
    template<class T> bool getInteger(const String& name, T& output) const
    {
        RefPtr<Value> value;
        if (!getValue(name, value))
            return false;

        return value->asInteger(output);
    }

    template<class T> Optional<T> getNumber(const String& name) const
    {
        RefPtr<Value> value;
        if (!getValue(name, value))
            return WTF::nullopt;

        T result;
        if (!value->asDouble(result))
            return WTF::nullopt;

        return result;
    }

    bool getString(const String& name, String& output) const;
    bool getObject(const String& name, RefPtr<Object>&) const;
    bool getArray(const String& name, RefPtr<Array>&) const;
    bool getValue(const String& name, RefPtr<Value>&) const;

    void remove(const String& name);

    void writeJSON(StringBuilder& output) const override;

    iterator begin() { return m_map.begin(); }
    iterator end() { return m_map.end(); }
    const_iterator begin() const { return m_map.begin(); }
    const_iterator end() const { return m_map.end(); }

    int size() const { return m_map.size(); }

protected:
    ObjectBase();

private:
    Dictionary m_map;
    Vector<String> m_order;
};

class Object : public ObjectBase {
public:
    static WTF_EXPORT_PRIVATE Ref<Object> create();

    using ObjectBase::asObject;

    // This class expected non-cyclic values, as we cannot serialize cycles in JSON.
    using ObjectBase::setBoolean;
    using ObjectBase::setInteger;
    using ObjectBase::setDouble;
    using ObjectBase::setString;
    using ObjectBase::setValue;
    using ObjectBase::setObject;
    using ObjectBase::setArray;

    using ObjectBase::find;
    using ObjectBase::getBoolean;
    using ObjectBase::getInteger;
    using ObjectBase::getDouble;
    using ObjectBase::getNumber;
    using ObjectBase::getString;
    using ObjectBase::getObject;
    using ObjectBase::getArray;
    using ObjectBase::getValue;

    using ObjectBase::remove;

    using ObjectBase::begin;
    using ObjectBase::end;

    using ObjectBase::size;
};


class WTF_EXPORT_PRIVATE ArrayBase : public Value {
public:
    typedef Vector<RefPtr<Value>>::iterator iterator;
    typedef Vector<RefPtr<Value>>::const_iterator const_iterator;

    unsigned length() const { return static_cast<unsigned>(m_map.size()); }

    RefPtr<Value> get(size_t index) const;

    size_t memoryCost() const final;

protected:
    virtual ~ArrayBase();

    bool asArray(RefPtr<Array>&) override;

    void pushBoolean(bool);
    void pushInteger(int);
    void pushDouble(double);
    void pushString(const String&);
    void pushValue(RefPtr<Value>&&);
    void pushObject(RefPtr<ObjectBase>&&);
    void pushArray(RefPtr<ArrayBase>&&);

    void writeJSON(StringBuilder& output) const override;

    iterator begin() { return m_map.begin(); }
    iterator end() { return m_map.end(); }
    const_iterator begin() const { return m_map.begin(); }
    const_iterator end() const { return m_map.end(); }

protected:
    ArrayBase();

private:
    Vector<RefPtr<Value>> m_map;
};

class Array : public ArrayBase {
public:
    static WTF_EXPORT_PRIVATE Ref<Array> create();

    using ArrayBase::asArray;

    // This class expected non-cyclic values, as we cannot serialize cycles in JSON.
    using ArrayBase::pushBoolean;
    using ArrayBase::pushInteger;
    using ArrayBase::pushDouble;
    using ArrayBase::pushString;
    using ArrayBase::pushValue;
    using ArrayBase::pushObject;
    using ArrayBase::pushArray;

    using ArrayBase::get;

    using ArrayBase::begin;
    using ArrayBase::end;
};


inline ObjectBase::iterator ObjectBase::find(const String& name)
{
    return m_map.find(name);
}

inline ObjectBase::const_iterator ObjectBase::find(const String& name) const
{
    return m_map.find(name);
}

inline void ObjectBase::setBoolean(const String& name, bool value)
{
    setValue(name, Value::create(value));
}

inline void ObjectBase::setInteger(const String& name, int value)
{
    setValue(name, Value::create(value));
}

inline void ObjectBase::setDouble(const String& name, double value)
{
    setValue(name, Value::create(value));
}

inline void ObjectBase::setString(const String& name, const String& value)
{
    setValue(name, Value::create(value));
}

inline void ObjectBase::setValue(const String& name, RefPtr<Value>&& value)
{
    ASSERT(value);
    if (m_map.set(name, WTFMove(value)).isNewEntry)
        m_order.append(name);
}

inline void ObjectBase::setObject(const String& name, RefPtr<ObjectBase>&& value)
{
    ASSERT(value);
    if (m_map.set(name, WTFMove(value)).isNewEntry)
        m_order.append(name);
}

inline void ObjectBase::setArray(const String& name, RefPtr<ArrayBase>&& value)
{
    ASSERT(value);
    if (m_map.set(name, WTFMove(value)).isNewEntry)
        m_order.append(name);
}

inline void ArrayBase::pushBoolean(bool value)
{
    m_map.append(Value::create(value));
}

inline void ArrayBase::pushInteger(int value)
{
    m_map.append(Value::create(value));
}

inline void ArrayBase::pushDouble(double value)
{
    m_map.append(Value::create(value));
}

inline void ArrayBase::pushString(const String& value)
{
    m_map.append(Value::create(value));
}

inline void ArrayBase::pushValue(RefPtr<Value>&& value)
{
    ASSERT(value);
    m_map.append(WTFMove(value));
}

inline void ArrayBase::pushObject(RefPtr<ObjectBase>&& value)
{
    ASSERT(value);
    m_map.append(WTFMove(value));
}

inline void ArrayBase::pushArray(RefPtr<ArrayBase>&& value)
{
    ASSERT(value);
    m_map.append(WTFMove(value));
}

template<typename T>
class ArrayOf : public ArrayBase {
private:
    ArrayOf() { }

    Array& castedArray()
    {
        COMPILE_ASSERT(sizeof(Array) == sizeof(ArrayOf<T>), cannot_cast);
        return *static_cast<Array*>(static_cast<ArrayBase*>(this));
    }

public:
    void addItem(RefPtr<T>&& value)
    {
        castedArray().pushValue(WTFMove(value));
    }
    
    void addItem(const String& value)
    {
        castedArray().pushString(value);
    }

    void addItem(int value)
    {
        castedArray().pushInteger(value);
    }

    void addItem(double value)
    {
        castedArray().pushDouble(value);
    }

    static Ref<ArrayOf<T>> create()
    {
        return adoptRef(*new ArrayOf<T>());
    }

    using ArrayBase::get;
    using ArrayBase::begin;
    using ArrayBase::end;
};

} // namespace JSONImpl

} // namespace WTF

namespace JSON {
using namespace WTF::JSONImpl;
}

