#pragma once

#include <string>

namespace ROSBridge {

namespace MessageGroups {

typedef std::string StringType;

template<typename Group, typename SubGroup, typename...MoreSubGroups>
struct MessageGroup {
    static StringType messageType() {return _full<Group, SubGroup, MoreSubGroups...>();}

    template<typename G, typename SubG, typename...MoreSubG>
    static StringType _full() {return G::label()+ "/" + _full<SubG, MoreSubG...>(); }
    template<typename G>
    static StringType _full() {return G::label(); }


    static StringType messageTypeLast() {return _last<Group, SubGroup, MoreSubGroups...>();}

    template<typename G, typename SubG, typename...MoreSubG>
    static StringType _last() {return _last<SubG, MoreSubG...>(); }
    template<typename G>
    static StringType _last() {return G::label(); }
};

//!
//! \note Each class belonging to a ROS message group must derive from \class MessageBaseClass.

namespace detail {

//!
//! \brief The EmptyGroup struct is used by the \class MessageBaseClass base class.
//!
//! The EmptyGroup struct is used by the \class MessageBaseClass base class. Passing a class using this
//! group will to the \class JsonFactory will lead to a compile-time error.
struct EmptyGroup        {
    static StringType label() {return "";}
};
}


struct GeometryMsgs {

    static StringType label() {return "geometry_msgs";}
    //!
    //! \brief The Point32Group struct is used the mark a class as a ROS Point32 message.
    //!
    //! The Point32Group struct is used the mark a class as a ROS Point32 message.
    struct Point32Group {
        static StringType label() {return "Point32";}
    };

    //!
    //! \brief The GeoPointGroup struct is used the mark a class as a ROS geographic_msgs/GeoPoint message.
    //!
    //! The GeoPointGroup struct is used the mark a class as a ROS geographic_msgs/GeoPoint message.
    struct GeoPointGroup {
        static StringType label() {return "GeoPoint";}
    };


    //!
    //! \brief The PolygonGroup struct is used the mark a class as a ROS Polygon message.
    //!
    //! The PolygonGroup struct is used the mark a class as a ROS Polygon message.
    struct PolygonGroup {
        static StringType label() {return "Polygon";}
    };

    //!
    //! \brief The PolygonStampedGroup struct is used the mark a class as a ROS PolygonStamped message.
    //!
    //! The PolygonStampedGroup struct is used the mark a class as a ROS PolygonStamped message.
    struct PolygonStampedGroup {
        static StringType label() {return "PolygonStamped";}
    };
};

struct GeographicMsgs {

    static StringType label() {return "geographic_msgs";}

    //!
    //! \brief The GeoPointGroup struct is used the mark a class as a ROS geographic_msgs/GeoPoint message.
    struct GeoPointGroup {
        static StringType label() {return "GeoPoint";}
    };
};

struct JSKRecognitionMsgs {

    static StringType label() {return "jsk_recognition_msgs";}

    //!
    //! \brief The PolygonArrayGroup struct is used the mark a class as a ROS jsk_recognition_msgs/PolygonArray message.
    //!
    //! The PolygonArrayGroup struct is used the mark a class as a ROS jsk_recognition_msgs/PolygonArray message.
    struct PolygonArrayGroup {
        static StringType label() {return "PolygonArray";}
    };
};

struct NemoMsgs {

    static StringType label() {return "nemo_msgs";}

    //!
    //! \brief The ProgressGroup struct is used the mark a class as a ROS nemo_msgs/Progress message.
    struct ProgressGroup {
        static StringType label() {return "Progress";}
    };

    //!
    //! \brief The HeartbeatGroup struct is used the mark a class as a ROS nemo_msgs/Heartbeat message.
    struct HeartbeatGroup {
        static StringType label() {return "Heartbeat";}
    };
};


typedef MessageGroup<detail::EmptyGroup,
                     detail::EmptyGroup>
        EmptyGroup;

typedef MessageGroups::MessageGroup<MessageGroups::GeometryMsgs,
                                    MessageGroups::GeometryMsgs::Point32Group>
        Point32Group;

typedef MessageGroups::MessageGroup<MessageGroups::GeographicMsgs,
                                    MessageGroups::GeographicMsgs::GeoPointGroup>
        GeoPointGroup;

typedef MessageGroups::MessageGroup<MessageGroups::GeometryMsgs,
                                    MessageGroups::GeometryMsgs::PolygonGroup>
        PolygonGroup;

typedef MessageGroups::MessageGroup<MessageGroups::GeometryMsgs,
                                    MessageGroups::GeometryMsgs::PolygonStampedGroup>
        PolygonStampedGroup;

typedef MessageGroups::MessageGroup<MessageGroups::JSKRecognitionMsgs,
                                    MessageGroups::JSKRecognitionMsgs::PolygonArrayGroup>
        PolygonArrayGroup;

typedef MessageGroups::MessageGroup<MessageGroups::NemoMsgs,
                                    MessageGroups::NemoMsgs::ProgressGroup>
        ProgressGroup;

typedef MessageGroups::MessageGroup<MessageGroups::NemoMsgs,
                                    MessageGroups::NemoMsgs::HeartbeatGroup>
        HeartbeatGroup;

} // end namespace MessageGroups

} // end namespace ros_bridge
