/* Subscriber interface
Copyright (C) 2020 Jonathan Hanks

This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/

#ifndef PUB_SUB2_SUB_HH
#define PUB_SUB2_SUB_HH

#include <functional>
#include <memory>
#include <string>
#include <vector>

#include <cds-pubsub/common.hh>
#include <cds-pubsub/sub_plugin.hh>

namespace pub_sub
{

    namespace detail
    {
        struct SubscriberIntl;
    }

    /*!
     * @brief The subscriber component of pub_sub.
     * @details A move only type that opens up and manages a connection to a
     * publisher.
     * It connects to the publisher and returns messages as they are received.
     * The lifecycle of the underlying transport (connection, reading, closing,
     * reconnecting, ...) is fully managed by the Subscriber.
     *
     * @note The publisher starts and controls a single background thread
     * which manages all connections and I/O.
     */
    class Subscriber
    {
    public:
        explicit Subscriber( );
        ~Subscriber( );

        Subscriber( const Subscriber& ) = delete;
        Subscriber( Subscriber&& ) = default;
        Subscriber& operator=( const Subscriber& ) = delete;
        Subscriber& operator=( Subscriber&& ) = default;

        /*!
         * @brief Load a subscription plugin
         * @param plugin The plugin api object
         */
        void load_plugin(
            std::shared_ptr< pub_sub::plugins::SubscriptionPluginApi > plugin );

        /*!
         * @brief Install a set of debug hooks, call prior to subscribing
         */
        void SetupDebugHooks( SubDebugNotices* debug_hooks );

        /*!
         * @brief start a Subscription
         * @param address The address as a number (ie "127.0.0.1") to connect to
         * @param handler The callback for messages
         * @return The new SubId representing this subscription.
         */
        SubId subscribe( const std::string& address, SubHandler handler );

        /*!
         * @brief Request that a subscription be restarted.
         * @param subscription_id the idea of the subscription.
         * @note this may not be supported for all subscription types.
         */
        void reset_subscription( SubId subscription_id );

    private:
        std::unique_ptr< detail::SubscriberIntl > p_;
    };

} // namespace pub_sub

#endif // PUB_SUB2_SUB_HH
