// This file is generated by Values_h.template.

// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef {{"_".join(config.protocol.namespace)}}_Values_h
#define {{"_".join(config.protocol.namespace)}}_Values_h

//#include "Allocator.h"
//#include "Forward.h"

{% for namespace in config.protocol.namespace %}
namespace {{namespace}} {
{% endfor %}

class ListValue;
class DictionaryValue;
class Value;

class {{config.lib.export_macro}} Value : public Serializable {
    PROTOCOL_DISALLOW_COPY(Value);
public:
    virtual ~Value() override { }

    static std::unique_ptr<Value> null()
    {
        return std::unique_ptr<Value>(new Value());
    }

    static std::unique_ptr<Value> parseBinary(const uint8_t* data, size_t size);

    enum ValueType {
        TypeNull = 0,
        TypeBoolean,
        TypeInteger,
        TypeDouble,
        TypeString,
        TypeBinary,
        TypeObject,
        TypeArray,
        TypeSerialized,
        TypeImported
    };

    ValueType type() const { return m_type; }

    bool isNull() const { return m_type == TypeNull; }

    virtual bool asBoolean(bool* output) const;
    virtual bool asDouble(double* output) const;
    virtual bool asInteger(int* output) const;
    virtual bool asString(String* output) const;
    virtual bool asBinary(Binary* output) const;

    virtual void writeJSON(StringBuilder* output) const;
    virtual void AppendSerialized(std::vector<uint8_t>* bytes) const override;
    virtual std::unique_ptr<Value> clone() const;
    String toJSONString() const;

protected:
    Value() : m_type(TypeNull) { }
    explicit Value(ValueType type) : m_type(type) { }

private:
    friend class DictionaryValue;
    friend class ListValue;

    ValueType m_type;
};

class {{config.lib.export_macro}} FundamentalValue : public Value {
public:
    static std::unique_ptr<FundamentalValue> create(bool value)
    {
        return std::unique_ptr<FundamentalValue>(new FundamentalValue(value));
    }

    static std::unique_ptr<FundamentalValue> create(int value)
    {
        return std::unique_ptr<FundamentalValue>(new FundamentalValue(value));
    }

    static std::unique_ptr<FundamentalValue> create(double value)
    {
        return std::unique_ptr<FundamentalValue>(new FundamentalValue(value));
    }

    bool asBoolean(bool* output) const override;
    bool asDouble(double* output) const override;
    bool asInteger(int* output) const override;
    void writeJSON(StringBuilder* output) const override;
    void AppendSerialized(std::vector<uint8_t>* bytes) const override;
    std::unique_ptr<Value> clone() const override;

private:
    explicit FundamentalValue(bool value) : Value(TypeBoolean), m_boolValue(value) { }
    explicit FundamentalValue(int value) : Value(TypeInteger), m_integerValue(value) { }
    explicit FundamentalValue(double value) : Value(TypeDouble), m_doubleValue(value) { }

    union {
        bool m_boolValue;
        double m_doubleValue;
        int m_integerValue;
    };
};

class {{config.lib.export_macro}} StringValue : public Value {
public:
    static std::unique_ptr<StringValue> create(const String& value)
    {
        return std::unique_ptr<StringValue>(new StringValue(value));
    }

    static std::unique_ptr<StringValue> create(const char* value)
    {
        return std::unique_ptr<StringValue>(new StringValue(value));
    }

    bool asString(String* output) const override;
    void writeJSON(StringBuilder* output) const override;
    void AppendSerialized(std::vector<uint8_t>* bytes) const override;
    std::unique_ptr<Value> clone() const override;

private:
    explicit StringValue(const String& value) : Value(TypeString), m_stringValue(value) { }
    explicit StringValue(const char* value) : Value(TypeString), m_stringValue(value) { }

    String m_stringValue;
};

class {{config.lib.export_macro}} BinaryValue : public Value {
public:
    static std::unique_ptr<BinaryValue> create(const Binary& value)
    {
        return std::unique_ptr<BinaryValue>(new BinaryValue(value));
    }

    bool asBinary(Binary* output) const override;
    void writeJSON(StringBuilder* output) const override;
    void AppendSerialized(std::vector<uint8_t>* bytes) const override;
    std::unique_ptr<Value> clone() const override;

private:
    explicit BinaryValue(const Binary& value) : Value(TypeBinary), m_binaryValue(value) { }

    Binary m_binaryValue;
};

class {{config.lib.export_macro}} SerializedValue : public Value {
public:
    static std::unique_ptr<SerializedValue> fromJSON(const String& value)
    {
        return std::unique_ptr<SerializedValue>(new SerializedValue(value));
    }

    static std::unique_ptr<SerializedValue> fromBinary(std::vector<uint8_t> value)
    {
        return std::unique_ptr<SerializedValue>(new SerializedValue(std::move(value)));
    }

    void writeJSON(StringBuilder* output) const override;
    std::vector<uint8_t> TakeSerialized() && override;
    void AppendSerialized(std::vector<uint8_t>* bytes) const override;
    std::unique_ptr<Value> clone() const override;

private:
    explicit SerializedValue(const String& json) : Value(TypeSerialized), m_serializedJSON(json) { }
    explicit SerializedValue(std::vector<uint8_t> binary) : Value(TypeSerialized), m_serializedBinary(std::move(binary)) { }
    SerializedValue(const String& json, const std::vector<uint8_t>& binary)
        : Value(TypeSerialized), m_serializedJSON(json), m_serializedBinary(binary) { }
    String m_serializedJSON;
    std::vector<uint8_t> m_serializedBinary;
};

class {{config.lib.export_macro}} DictionaryValue : public Value {
public:
    using Entry = std::pair<String, Value*>;
    static std::unique_ptr<DictionaryValue> create()
    {
        return std::unique_ptr<DictionaryValue>(new DictionaryValue());
    }

    static DictionaryValue* cast(Value* value)
    {
        if (!value || value->type() != TypeObject)
            return nullptr;
        return static_cast<DictionaryValue*>(value);
    }

    static std::unique_ptr<DictionaryValue> cast(std::unique_ptr<Value> value)
    {
        return std::unique_ptr<DictionaryValue>(DictionaryValue::cast(value.release()));
    }

    void writeJSON(StringBuilder* output) const override;
    void AppendSerialized(std::vector<uint8_t>* bytes) const override;
    std::unique_ptr<Value> clone() const override;

    size_t size() const { return m_data.size(); }

    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, std::unique_ptr<Value>);
    void setObject(const String& name, std::unique_ptr<DictionaryValue>);
    void setArray(const String& name, std::unique_ptr<ListValue>);

    bool getBoolean(const String& name, bool* output) const;
    bool getInteger(const String& name, int* output) const;
    bool getDouble(const String& name, double* output) const;
    bool getString(const String& name, String* output) const;

    DictionaryValue* getObject(const String& name) const;
    ListValue* getArray(const String& name) const;
    Value* get(const String& name) const;
    Entry at(size_t index) const;

    bool booleanProperty(const String& name, bool defaultValue) const;
    int integerProperty(const String& name, int defaultValue) const;
    double doubleProperty(const String& name, double defaultValue) const;
    void remove(const String& name);

    ~DictionaryValue() override;

private:
    DictionaryValue();
    template<typename T>
    void set(const String& key, std::unique_ptr<T>& value)
    {
        DCHECK(value);
        bool isNew = m_data.find(key) == m_data.end();
        m_data[key] = std::move(value);
        if (isNew)
            m_order.push_back(key);
    }

    using Dictionary = std::unordered_map<String, std::unique_ptr<Value>>;
    Dictionary m_data;
    std::vector<String> m_order;
};

class {{config.lib.export_macro}} ListValue : public Value {
public:
    static std::unique_ptr<ListValue> create()
    {
        return std::unique_ptr<ListValue>(new ListValue());
    }

    static ListValue* cast(Value* value)
    {
        if (!value || value->type() != TypeArray)
            return nullptr;
        return static_cast<ListValue*>(value);
    }

    static std::unique_ptr<ListValue> cast(std::unique_ptr<Value> value)
    {
        return std::unique_ptr<ListValue>(ListValue::cast(value.release()));
    }

    ~ListValue() override;

    void writeJSON(StringBuilder* output) const override;
    void AppendSerialized(std::vector<uint8_t>* bytes) const override;
    std::unique_ptr<Value> clone() const override;

    void pushValue(std::unique_ptr<Value>);

    Value* at(size_t index);
    size_t size() const { return m_data.size(); }
    void reserve(size_t capacity) { m_data.reserve(capacity); }

private:
    ListValue();
    std::vector<std::unique_ptr<Value>> m_data;
};

void escapeLatinStringForJSON(const uint8_t* str, unsigned len, StringBuilder* dst);
void escapeWideStringForJSON(const uint16_t* str, unsigned len, StringBuilder* dst);

{% for namespace in config.protocol.namespace %}
} // namespace {{namespace}}
{% endfor %}

#endif // {{"_".join(config.protocol.namespace)}}_Values_h
