// 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 %}

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

namespace {{config.crdtp.namespace}} {

template <typename T>
struct ProtocolTypeTraits<
    std::unique_ptr<T>,
    typename std::enable_if<
        std::is_base_of<{{"::".join(config.imported.namespace)}}::Exported, T>::value>::type> {
  static bool Deserialize(DeserializerState* state, std::unique_ptr<T>* value) {
    if (state->tokenizer()->TokenTag() != cbor::CBORTokenTag::ENVELOPE) {
      state->RegisterError(Error::CBOR_INVALID_ENVELOPE);
      return false;
    }
    span<uint8_t> env = state->tokenizer()->GetEnvelope();
    auto res = T::fromBinary(env.data(), env.size());
    if (!res) {
      // TODO(caseq): properly plumb an error rather than returning a bogus code.
      state->RegisterError(Error::MESSAGE_MUST_BE_AN_OBJECT);
      return false;
    }
    *value = std::move(res);
    return true;
  }
  static void Serialize(const std::unique_ptr<T>& value, std::vector<uint8_t>* bytes) {
    // Use virtual method, so that outgoing protocol objects could be retained
    // by a pointer to ProtocolObject.
    value->AppendSerialized(bytes);
  }
};

template <typename T>
struct ProtocolTypeTraits<
    T,
    typename std::enable_if<
        std::is_base_of<{{"::".join(config.imported.namespace)}}::Exported, T>::value>::type> {
  static void Serialize(const T& value, std::vector<uint8_t>* bytes) {
    // Use virtual method, so that outgoing protocol objects could be retained
    // by a pointer to ProtocolObject.
    value.AppendSerialized(bytes);
  }
};

}  // namespace {{config.crdtp.namespace}}

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

{% 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 AppendSerialized(std::vector<uint8_t>* output) const override {
        m_exported->AppendSerialized(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);
    }
};

  {% endfor %}

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

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