/* Sample publisher
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 <algorithm>
#include <chrono>
#include <iostream>
#include <memory>
#include <thread>

#include <cds-pubsub/pub.hh>

std::array< char*, 100 > arena{};

void
fill_arena( )
{
    for ( auto& ptr : arena )
    {
        ptr = new char[ 20000 ];
    }
}

char*
take_from_arena( )
{
    for ( auto& ptr : arena )
    {
        if ( ptr != nullptr )
        {
            char* tmp = ptr;
            ptr = nullptr;
            return tmp;
        }
    }
    throw std::bad_alloc( );
}

void
return_to_arena( char* p )
{
    for ( auto& ptr : arena )
    {
        if ( ptr == nullptr )
        {
            ptr = p;
            return;
        }
    }
    throw std::runtime_error( "Overflowed arena!" );
}

const int msg_size = 500000;

class PubDebug : public pub_sub::PubDebugNotices
{
public:
    PubDebug( )
    {
    }
    ~PubDebug( ) override{};

    void
    retransmit_request_seen( const pub_sub::KeyType type,
                             int                    packet_count ) override
    {
    }

    void
    retransmit_sent( const pub_sub::KeyType key, int packet_count ) override
    {
        std::cout << "Retransmit request sent " << key << " " << packet_count
                  << std::endl;
    }
};

int
main( int argc, char* argv[] )
{
    PubDebug debug;
    // fill_arena( );
    // pub_sub::Publisher p( "127.0.0.1:9000" );
    // pub_sub::Publisher p( "udp://127.0.0.1/127.255.255.255:9000" );

    std::string conn_str = "multi://127.0.0.1/239.192.0.1:9000";
    if ( argc == 2 )
    {
        conn_str = argv[ 1 ];
    }
    std::cout << "connecting to " << conn_str << std::endl;
    pub_sub::Publisher p( conn_str, &debug );

    int i = 0;
    while ( true )
    {
        // auto ptr = take_from_arena( );
        pub_sub::DataPtr ptr( new unsigned char[ msg_size ] );
        //        long usecount = ptr.use_count();
        // pub_sub::DataPtr ptr2(new unsigned char[200000]);
        //        //pub_sub::DataPtr ptr2 = std::make_shared< unsigned char[] >(
        //        200000 );
        //        //auto ptr = std::make_unique< char[] >( 200000 );
        std::fill( ptr.get( ), ptr.get( ) + msg_size, i % 256 );
        std::cout << "publishing " << i << " as " << ( i % 256 ) << std::endl;
        p.publish( i, pub_sub::Message( ptr, msg_size ) );
        ++i;
        std::this_thread::sleep_for( std::chrono::milliseconds( 125 ) );
    }
    return 0;
}
