/* pub_sub publisher implementation
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/>.
*/
#include <cds-pubsub/pub.hh>
#include "pub_sub_intl.hh"

#include <memory>

#include "pub_intl.hh"
#include "pub_plugins_intl.hh"

namespace pub_sub
{
    namespace detail
    {
        std::unique_ptr< detail::PublisherIntl >
        create_publisher_intl( PubDebugNotices* debug )
        {
            /* read the environment once per Publisher, not per destination */
            auto options = PublisherOptions::from_environment( );
            auto publisher = std::make_unique< detail::PublisherIntl >( debug );
            publisher->load_plugin(
                std::make_shared< TcpPublisherPluginApi >( options ) );
            publisher->load_plugin(
                std::make_shared< UdpPublisherPluginApi >( options ) );
            publisher->load_plugin(
                std::make_shared< UdpMultiPublisherPluginApi >( options ) );
            publisher->load_plugin(
                std::make_shared< PubPluginZLibFilter >( ) );
            return publisher;
        }
    } // namespace detail

    Publisher::Publisher( PubDebugNotices* debug )
        : p_{ detail::create_publisher_intl( debug ) }
    {
    }

    Publisher::Publisher( const std::string& address, PubDebugNotices* debug )
        : p_{ detail::create_publisher_intl( debug ) }
    {
        p_->add_destination( address );
    }
    Publisher::~Publisher( ) = default;

    void
    Publisher::load_plugin(
        std::shared_ptr< pub_sub::plugins::PublisherPluginApi > plugin )
    {
        if ( !plugin )
        {
            return;
        }
        p_->load_plugin( std::move( plugin ) );
    }

    void
    Publisher::add_destination( const std::string& address )
    {
        if ( address.empty( ) )
        {
            return;
        }
        p_->add_destination( address );
    }

    void
    Publisher::publish( KeyType key, Message msg )
    {
        if ( msg.length > MAX_MSG_SIZE( ) )
        {
            throw std::runtime_error( "The given message is too big" );
        }
        p_->publish( key, msg );
    }
} // namespace pub_sub
