// 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"

#include {{format_include(config.protocol.package, "Forward")}}

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

class ListValue;
class DictionaryValue;
class Value;

#define PROTOCOL_DISALLOW_COPY(ClassName) \
 private:                                 \
  ClassName(const ClassName&) = delete;   \
  ClassName& operator=(const ClassName&) = delete

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,
        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 AppendSerialized(std::vector<uint8_t>* bytes) const override;
    virtual std::unique_ptr<Value> clone() 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 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 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 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}} 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 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 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;
};

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

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