// This file is generated by Imported_h.template.

// Copyright (c) 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)}}_{{domain.domain}}_imported_h
#define {{"_".join(config.protocol.namespace)}}_{{domain.domain}}_imported_h

#include {{format_include(config.protocol.package, "Protocol")}}
{% if config.imported.header %}
#include {{format_include(config.imported.header)}}
{% else %}
#include {{format_include(config.imported.package, domain.domain)}}
{% endif %}

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

using Exported = {{"::".join(config.imported.namespace)}}::Exported;

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

class {{config.lib.export_macro}} ImportedValue : public Value {
public:
    static std::unique_ptr<ImportedValue> fromExported(const Exported* value) {
        return std::unique_ptr<ImportedValue>(new ImportedValue(value));
    }

    void writeJSON(StringBuilder* output) const override {
        auto json = m_exported->toJSONString();
        String local_json = ({{config.imported.from_imported_string % "std::move(json)"}});
        StringUtil::builderAppend(*output, local_json);
    }
    void AppendSerialized(std::vector<uint8_t>* output) const override {
        m_exported->writeBinary(output);
    }
    std::unique_ptr<Value> clone() const override {
        return std::unique_ptr<Value>(new ImportedValue(m_exported));
    }

private:
    explicit ImportedValue(const Exported* exported) : Value(TypeImported), m_exported(exported) { }
    const Exported* m_exported;
};

#endif // !defined({{"_".join(config.protocol.namespace)}}_imported_imported_h)

  {% for type in domain.types %}
    {% if not (type.type == "object") or not ("properties" in type) or not protocol.is_imported(domain.domain, type.id) %}{% continue %}{% endif %}

template<>
struct ValueConversions<{{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}> {
    static std::unique_ptr<{{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}> fromValue(protocol::Value* value, ErrorSupport* errors)
    {
        if (!value) {
            errors->addError("value expected");
            return nullptr;
        }

        std::vector<uint8_t> binary;
        value->AppendSerialized(&binary);
        auto result = {{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}::fromBinary(binary.data(), binary.size());
        if (!result)
            errors->addError("cannot parse");
        return result;
    }

    static std::unique_ptr<protocol::Value> toValue(const {{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}* exported)
    {
        return ImportedValue::fromExported(exported);
    }

    static std::unique_ptr<protocol::Value> toValue(const std::unique_ptr<{{"::".join(config.imported.namespace)}}::{{domain.domain}}::API::{{type.id}}>& value)
    {
        return toValue(value.get());
    }
};

  {% endfor %}

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

#endif // !defined({{"_".join(config.protocol.namespace)}}_{{domain.domain}}_imported_h)
