// 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 writeBinary(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->writeBinary(&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)
