/*
 * Copyright Staffan Gimåker 2008-2010.
 *
 * ---
 *
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or copy at
 * http://www.boost.org/LICENSE_1_0.txt)
 */

#ifndef PEEKABOT_CLIENT_VERTEX_BASED_PROXY_HH_INCLUDED
#define PEEKABOT_CLIENT_VERTEX_BASED_PROXY_HH_INCLUDED


#include "ObjectProxy.hh"
#include "../DelayedDispatch.hh"
#include "../../Deprecated.hh"

#include <boost/scoped_ptr.hpp>
#include <cstddef>


namespace peekabot
{
    namespace client
    {
        /**
         * \brief A sequence of vertices, that's used to pass vertices to
         * vertex-based object proxies.
         *
         * \sa ColoredVertexSet
         */
        class PEEKABOT_API VertexSet
        {
            friend class VertexBasedProxyBase;

        public:
            VertexSet();

            VertexSet(const VertexSet &other);

            ~VertexSet();

            VertexSet &operator=(const VertexSet &other);

            /**
             * \deprecated Deprecated in peekabot 0.8.0. Use add() instead.
             */
            void add_vertex(
                float x, float y, float z) PEEKABOT_DEPRECATED;

            /**
             * \since peekabot 0.8.0
             */
            void add(float x, float y, float z);

            void clear();

            std::size_t size() const;

            bool empty() const;

        private:
            class Impl;
            boost::scoped_ptr<Impl> m_impl;
        };


        /**
         * \brief A sequence of vertices with color information, that's used to
         * pass vertices to vertex-based object proxies.
         *
         * This class is identical to VertexSet except it allows per-vertex
         * colors to be specified as well.
         *
         * \since peekabot 0.8.0
         */
        class PEEKABOT_API ColoredVertexSet
        {
            friend class VertexBasedProxyBase;

        public:
            ColoredVertexSet();

            ColoredVertexSet(const ColoredVertexSet &other);

            ~ColoredVertexSet();

            ColoredVertexSet &operator=(const ColoredVertexSet &other);

            void add(
                float x, float y, float z,
                float r, float g, float b);

            void clear();

            std::size_t size() const;

            bool empty() const;

        private:
            class Impl;
            boost::scoped_ptr<Impl> m_impl;
        };


        /**
         * \brief Base class for all proxies to vertex-based objects.
         */
        class PEEKABOT_API VertexBasedProxyBase : virtual public ObjectProxyBase
        {
        public:
            typedef peekabot::client::VertexSet VertexSet;


            VertexBasedProxyBase();

            VertexBasedProxyBase(const VertexBasedProxyBase &p);

            /**
             * \brief Set the vertices of the object.
             *
             * \param vertices The vertices to set the remote object's
             * vertices to.
             */
            DelayedDispatch set_vertices(const VertexSet &vertices);

            /**
             * \brief Add one or more vertices to the object.
             *
             * \param vertices The vertices to add to the object.
             */
            DelayedDispatch add_vertices(const VertexSet &vertices);

            /**
             * \copydoc set_vertices(const VertexSet &)
             */
            DelayedDispatch set_vertices(const ColoredVertexSet &vertices);

            /**
             * \copydoc add_vertices(const VertexSet &)
             */
            DelayedDispatch add_vertices(const ColoredVertexSet &vertices);

            /**
             * \brief Add a single vertex to the object.
             *
             * \remark If you're adding several vertices, using
             * add_vertices(const VertexSet &) is a lot more efficient.
             *
             * \deprecated Deprecated in peekabot 0.8. Use VertexSet in
             * conjunction with add_vertices() instead.
             */
            DelayedDispatch add_vertex(
                float x, float y, float z) PEEKABOT_DEPRECATED;

            /**
             * \brief Remove all vertices of the remote object.
             */
            DelayedDispatch clear_vertices();

            /**
             * \brief Automatically keep the number of vertices in the object
             * below or at the specified value.
             *
             * This is very useful when visualizing, for example, the path
             * that a robot has traversed, since it might grow very large if
             * left unchecked. Vertex-based objects whose vertices are
             * updated continuously consume significant CPU resources when
             * they grow large.
             *
             * Setting the max vertices option to 0 (the default) disables
             * this functionality.
             * The behaviour when the vertices overflow is controlled by
             * set_vertex_overflow_policy().
             */
            DelayedDispatch set_max_vertices(boost::uint32_t n);

            /**
             * \brief Set the policy for resolving vertex overflows.
             *
             * Depending on the value supplied, the vertices are either
             * cleared, truncated or truncated to half their size, where the
             * latter is the default. When truncating, "older" vertices are
             * removed first.
             *
             * \sa set_max_vertices()
             */
            DelayedDispatch set_vertex_overflow_policy(
                VertexOverflowPolicy overflow_policy);
        };

        /**
         * \brief Proxy class usable with any type of object that is
         * vertex-based.
         */
        class PEEKABOT_API VertexBasedProxy : public VertexBasedProxyBase
        {
        public:
            VertexBasedProxy();

            VertexBasedProxy(const VertexBasedProxyBase &p);

            VertexBasedProxy &operator=(const VertexBasedProxy &p);

            VertexBasedProxy &operator=(const VertexBasedProxyBase &p);

            /**
             * \copydoc ScalableProxy::assign(const ObjectProxyBase&)
             */
            DelayedDispatch assign(const ObjectProxyBase &p);

            /**
             * \copydoc ObjectProxy::assign(PeekabotClient&,const std::string&)
             */
            DelayedDispatch assign(
                PeekabotClient &client,
                const std::string &path);

            /**
             * \copydoc
             * ObjectProxy::assign(const ObjectProxyBase&,const std::string&)
             */
            DelayedDispatch assign(
                const ObjectProxyBase &parent,
                const std::string &rel_path);
        };
    }
}


#endif // PEEKABOT_CLIENT_VERTEX_BASED_PROXY_HH_INCLUDED
