#pragma once
#include "ros_bridge/include/MessageBaseClass.h"
#include "ros_bridge/include/MessageTag.h"
#include "ros_bridge/include/TypeFactory.h"
#include "ros_bridge/include/JsonFactory.h"

#include <memory>
#include "rapidjson/include/rapidjson/document.h"

namespace ROSBridge {

class CasePacker
{
    typedef MessageTag Tag;
    typedef rapidjson::Document JsonDoc;
    typedef std::unique_ptr<JsonDoc> JsonDocUPtr;
public:
    CasePacker() = delete;
    CasePacker(TypeFactory *typeFactory, JsonFactory *jsonFactory);

    template<class T>
    JsonDocUPtr pack(const T &msg, const std::string &topic) const
    {
        JsonDocUPtr docPt(_jsonFactory->create(msg));
        std::string messageType = T::Group::messageType();
        addTag(docPt, topic, messageType.c_str());
        return docPt;
    }

    template<class T>
    bool unpack(JsonDocUPtr &pDoc, T &msg) const {
        removeTag(pDoc);
        return _typeFactory->create(*pDoc.get(), msg);
    }


    bool getTag(const JsonDocUPtr &pDoc, Tag &tag) const;
    void addTag        (JsonDocUPtr &doc,
                         const std::string &topic,
                         const std::string &messageType) const;
    void addTag        (JsonDocUPtr &doc, const Tag &tag) const;
    void removeTag     (JsonDocUPtr &pDoc) const;
    bool getTopic      (const JsonDocUPtr &pDoc, std::string &topic) const;
    bool getMessageType(const JsonDocUPtr &pDoc, std::string &messageType) const;

    static const char* topicKey;
    static const char* messageTypeKey;

private:
    TypeFactory *_typeFactory;
    JsonFactory *_jsonFactory;
};
}

