#pragma once


#include "WHISPER/whisper.hpp"
#include <cstdint>
#include <list>
#include <memory>
#include <vector>

#define ZMQ_BUILD_DRAFT_API 1
#include <zmq.hpp>
#include <zmq_addon.hpp>

namespace WHISPER {


    struct localClient{
        std::uint32_t port;
        std::string addr;
        std::uint32_t id;
        zmq::socket_t clientSocket;

        };





    class InternalUDPService : public whispercomm {


        private:
            /// ip address of the destination 
            std::string destinationAdress_;
            /// my own ipadress
            std::string myAdress_;
            /// sending port
            std::uint16_t port_;
            /// port wich i bind to 
            std::uint16_t ownReceivingPort_;

            ///zeromq io contex 
            zmq::context_t ctx;
            /// socket for sending 
            zmq::socket_t sender;
            ///shared pointer to receiving socket 
            std::shared_ptr<zmq::socket_t> receiver = nullptr;
            /// shared pointer to loopback sending socket
            std::shared_ptr<zmq::socket_t> loopbackSocket = nullptr;
            /// vector of local udp clients
            std::list<std::shared_ptr<localClient>> localclients;
            

            std::atomic<bool> stopReceiving = false;


            /**
            * @brief checks if the given port is already is use
            * @param std:uint16 port
            * @param returns the original port or a new free port
            */
            std::uint16_t checkPort(std::uint16_t port);

            void derivedConnect() override;
            void derivedDisconnect() override;
            void derivedPublish(std::string msg,std::string topic) override;
            void derivedReceive() override;
            void derivedSubscribe(std::string topic) override;
            void derivedUnsubscribe(std::string topic) override;

            void sendToLocalClients(std::string  msg,std::string topic);
            




        public:
            InternalUDPService(std::uint32_t id, SourceType owndevicetype,std::uint16_t port, std::string destinationAdress, std::string myAdress);




    };




}